Skip to content

Latest commit

 

History

History
225 lines (175 loc) · 5.51 KB

274.md

File metadata and controls

225 lines (175 loc) · 5.51 KB
Info

Example

#include <tuple>
#include <cassert>

int main() {
  auto [first, ...ts] = std::tuple{1, 2 ,3};
  assert(1 == first);
}

https://godbolt.org/z/7aax7P3c5

Puzzle

  • Can you implement a function which returns first and last elements from a variadic pack?
[[nodiscard]] constexpr auto first_and_last(auto... args); // TODO

int main() {
  using namespace boost::ut;

  "first and last"_test = [] {
     expect(std::tuple{1, 2} == first_and_last(1, 2));
     expect(std::tuple{1, 3} == first_and_last(1, 2, 3));
     expect(std::tuple{0, 2} == first_and_last(0, 10, 2));
  };
}

https://godbolt.org/z/ax7Tnxh18

Solutions

[[nodiscard]] constexpr auto first_and_last(auto... args)
{
    auto [first, ...ts] = std::tuple{args...};
    auto tail = std::tuple{ts...};
    return std::tuple{first, std::get<sizeof...(ts) - 1>(tail)};
}

https://godbolt.org/z/eq74xv991

[[nodiscard]] constexpr auto first_and_last(auto... args) {
    auto const [first, ...tail] = std::tuple{args...};
    auto const [...mid, last] = std::tuple{args...}; // Note, using `tail` here causes ICE.
    return std::tuple{first, last};
}

https://godbolt.org/z/nqbnz6W1f

[[nodiscard]] constexpr auto first_and_last(auto... args)
    requires(sizeof...(args) == 2)
{
    // This function is only needed because an empty pack seems to ICE in every
    // way I could think of writing it. Remove this overload for a demonstration
    // of the ICE.
    return std::tuple{args...};
}

[[nodiscard]] constexpr auto first_and_last(auto... args) {
    auto [first, ... _, last] = std::tuple{args...};
    return std::tuple{first, last};
}

https://godbolt.org/z/ejcxnPP4s

[[nodiscard]] constexpr auto first_and_last(auto... args); // TODO

int main() {
  using namespace boost::ut;

  "first and last"_test = [] {
     expect(std::tuple{1, 2} == first_and_last(1, 2));
     expect(std::tuple{1, 3} == first_and_last(1, 2, 3));
     expect(std::tuple{0, 2} == first_and_last(0, 10, 2));
  };
}

https://godbolt.org/z/ax7Tnxh18

[[nodiscard]] constexpr auto first_and_last(auto... args) requires (sizeof...(args) >= 2) {
  auto [first, ...suffix] = std::tuple{args...};
  auto [...prefix, last] = std::tuple{args...};
  return std::tuple{first, last};
}

https://godbolt.org/z/fGTs5vc1v

[[nodiscard]] constexpr auto first_and_last(auto first, auto last) {
    return std::tuple{first, last};
}

[[nodiscard]] constexpr auto first_and_last(auto... args) requires (sizeof...(args) > 2) {
    auto [first, ...ts, last] = std::tuple{args...};
    return std::tuple{first, last};
}

https://godbolt.org/z/4W9Ws3q8v

[[nodiscard]] constexpr auto first_and_last(auto arg1, auto arg2, auto... args){
  return std::make_tuple(arg1, [](auto recur, auto ... args){
      return recur(recur, args ...);
    }([](auto recur, auto arg, auto ... args){
        if constexpr(sizeof ... (args) == 0){
          return arg;
        } else {
          return recur(recur, args ...);
        }
      }, arg2, args ...));
}

https://godbolt.org/z/oPTnPbfno

[[nodiscard]] constexpr auto first_and_last(auto... args) {
     return std::make_tuple(std::get<0>(std::make_tuple(args...)), std::get<sizeof...(args)-1>(std::make_tuple(args...))   );
}

https://godbolt.org/z/W47jWGssn

[[nodiscard]] constexpr auto first_and_last(auto... args) requires (sizeof...(args) == 2){
    auto [first, last] = std::tuple{args...};
    return std::tuple{first, last};
}

[[nodiscard]] constexpr auto first_and_last(auto... args) requires (sizeof...(args) > 2){
    auto [first, ...mid, last] = std::tuple{args...};
    return std::tuple{first, last};
}

https://godbolt.org/z/sPT9nv464

constexpr auto last(auto... args) {
    const auto [...rest, _last] = std::tuple{args...};
    return _last;
}

constexpr auto first(auto... args) {
    const auto [_first, ...rest] = std::tuple{args...};
    return _first;
}

[[nodiscard]] constexpr auto first_and_last(auto... args){
    return std::tuple{first(args...), last(args...)};
}

https://godbolt.org/z/c15h1GT6E

[[nodiscard]] constexpr auto first_and_last(auto first, auto... args) {
    return std::tuple{first, (args, ...)};
}

https://godbolt.org/z/WordnMWTT

[[nodiscard]] constexpr auto first_and_last(auto... args) {
  if constexpr (sizeof...(args) != 2) {
    auto [first, ... values, last] = std::tuple{args...};
    return std::tuple{first, last};
  } else {
    return std::tuple{args...};
  }
}

https://godbolt.org/z/5Eqcf7ejM

[[nodiscard]] constexpr auto first_and_last(auto... args){
    std::common_type_t<decltype(args)...> first;
    (void)(((first = args, true) || ...));
    std::common_type_t<decltype(args)...> last;
    (void)(((last = args, false) || ...));
    return std::make_tuple(first,last);
}

https://godbolt.org/z/T6PaMKK7M

[[nodiscard]] constexpr auto first_and_last(auto... args){
    auto [first, ...ts, last] = std::tuple<decltype(args)...>(args...);
    return std::make_tuple(first,last);
}

https://godbolt.org/z/9a34WaE8f

[[nodiscard]] constexpr auto first_and_last(auto first, auto... rest) {
  return std::tuple{first, (..., (rest = rest))};
}

https://godbolt.org/z/zfPTTYrjG