Skip to content

Latest commit

 

History

History
292 lines (229 loc) · 7.05 KB

250.md

File metadata and controls

292 lines (229 loc) · 7.05 KB
Info

  • Did you know about methods to access the last element of variadic pack...?

Example

template<class, std::size_t> concept Any = true;

constexpr auto last1 = [](auto... args) {
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    return [](Any<Ns> auto..., auto last) {
      return last;
    }(args...);
  }
  (std::make_index_sequence<sizeof...(args) - 1>{});
};

auto last2 = [](auto... args) {
  return (args, ...);
};

static_assert(1 == last1(1));
static_assert(2 == last1(1, 2));
static_assert(3 == last1(1, 2, 3));

static_assert(1 == last2(1));
static_assert(2 == last2(1, 2));
static_assert(3 == last2(1, 2, 3));

https://godbolt.org/z/599K9eah8

Puzzle

  • Can you implement nth_element which returns Nth element of variadic pack...?
template<auto N>
constexpr auto nth_element; // TODO

static_assert(1 == nth_element<0>(1));
static_assert(1 == nth_element<0>(1, 2));
static_assert(2 == nth_element<1>(1, 2));
static_assert(1 == nth_element<0>(1, 2, 3));
static_assert(2 == nth_element<1>(1, 2, 3));
static_assert(3 == nth_element<2>(1, 2, 3));

https://godbolt.org/z/1aPcePYPE

Solutions

template<auto N>
constexpr auto nth_element = [](auto...args){
    return std::get<N>(std::tuple{args...});
};

https://godbolt.org/z/vqKfzevbK

template <typename, std::size_t> concept prefix = true;

template <auto N>
constexpr auto nth_element(auto... args) {
  return [&]<auto... Is>(std::index_sequence<Is...>) {
    return [] (prefix<Is> auto..., auto arg, auto...) {
      return arg;
    }(args...);
  }(std::make_index_sequence<N>());
}

https://godbolt.org/z/WPhe5MerW

template<class T, std::size_t N> struct any { T value{}; };

template<std::size_t N, class T>
constexpr decltype(auto) get(any<T, N>& t) { return t.value; }

template<auto N>
constexpr auto nth_element = [](auto... args) {
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    struct : any<decltype(args), Ns>... { } _{args...};
    return get<N>(_);
  }
  (std::make_index_sequence<sizeof...(args)>{});
};

https://godbolt.org/z/aEM31WE8b

template<auto N>
constexpr auto nth_element = [](auto... args) {
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    return [](decltype((void*)Ns)..., auto* nth, auto*...) {
      return *nth;
    }(&args...);
  }
  (std::make_index_sequence<N>{});
};

https://godbolt.org/z/a8vsqM848

template<class T, std::size_t N> struct any { T value{}; };

template<auto N>
constexpr auto nth_element = [](auto... args) {
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    struct : any<decltype(args), Ns>... { } _{args...};
    return static_cast<__type_pack_element<N, any<decltype(args), Ns>...>&>(_).value;
  }
  (std::make_index_sequence<sizeof...(args)>{});
};

https://godbolt.org/z/GMGnWfvnE

template<auto N>
constexpr auto nth_element = [](auto arg, auto... args)
  requires (std::is_same_v<decltype(arg), decltype(args)> and ...) {
  return std::array{arg, args...}[N];
};

https://godbolt.org/z/1G7Gj16nx

template<auto N, auto I = 0>
constexpr auto nth_element(auto arg, auto... args) {
    if constexpr (I == N) {
        return arg;
    } else if constexpr (sizeof...(args) > 0u) {
        return nth_element<N, I + 1>(args...);
    }
}

https://godbolt.org/z/vGh1nTnaq

template<class T, std::size_t N> struct any { T value{}; };

template<auto N>
constexpr auto nth_element = [](auto... args) {
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    struct : any<decltype(args), Ns>... { } _{args...};
    return static_cast<boost::mp11::mp_at_c<boost::mp11::mp_inherit<any<decltype(args), Ns>...>, N>&>(_).value;
  }
  (std::make_index_sequence<sizeof...(args)>{});
};

https://godbolt.org/z/rKjzPf9zK

template<class, std::size_t> concept Any = true;

template<auto N>
constexpr auto nth_element(auto... pack) {
    return [&]<auto... Is>(std::index_sequence<Is...>) {
        return [](Any<Is> auto..., auto arg, auto...) {
            return arg;
        }(pack...);
    }(std::make_index_sequence<N>{});
}

https://godbolt.org/z/bao1dsY5q

template<class, std::size_t> concept Any = true;
template<auto N>
constexpr auto nth_element( auto ...  args )
{
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    return [](Any<Ns> auto ..., auto nth, auto ... ) {
      return nth;
    }(args...);
  }(std::make_index_sequence<N>{});
}

https://godbolt.org/z/78b1qd3cE

namespace detail {

#define NTH_ARG(Z, N, TYPE) TYPE arg##N,
#define NTH_ELEMENT(Z, N, TYPE)                                                \
  template <auto I>                                                            \
  requires(I == N) constexpr decltype(auto) nth_element(                       \
      BOOST_PP_REPEAT(BOOST_PP_INC(N), NTH_ARG, TYPE) TYPE...) {               \
    return arg##N;                                                             \
  }

BOOST_PP_REPEAT(BOOST_PP_DEC(BOOST_PP_LIMIT_REPEAT), NTH_ELEMENT, auto &&)

#undef NTH_ELEMENT
#undef NTH_ARG

} // namespace detail

template <auto N> constexpr decltype(auto) nth_element(auto &&...args) {
  return detail::nth_element<N>(args...);
}

https://godbolt.org/z/ervdav89b

template <class, std::size_t>
concept Any = true;

template <auto N> constexpr decltype(auto) nth_element(auto &&...args) {
  return [&]<auto... Is>(std::index_sequence<Is...>) -> decltype(auto) {
    return [](Any<Is> auto &&..., auto &&arg, auto &&...) -> decltype(auto) {
      return arg;
    }(args...);
  }(std::make_index_sequence<N>{});
}

https://godbolt.org/z/515fP7WbW

template <std::size_t N>
requires (N == 0)
constexpr auto nth_element(auto&& arg0, auto&&...) {
    return arg0;
}

template <std::size_t N>
requires (N > 0) constexpr auto nth_element(auto&& arg0, auto&&... rest) {
    return nth_element<N-1>(std::forward<decltype(rest)>(rest)...);
}

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

template<auto N>
constexpr auto nth_element = [](auto... args) {
    static_assert(N < sizeof...(args));
    return std::array{args...}[N];
};

https://godbolt.org/z/vGnM4GnE4

template<auto N>
constexpr decltype(auto) nth_element(auto &&... args) {
    using namespace boost::mp11;
    return [&] <class... Ts> (mp_list<Ts...>) -> decltype(auto) {
        return [] (Ts &&..., auto &&arg, auto &&...) -> decltype(auto) {
            return arg;
        }(std::forward<decltype(args)>(args)...);
    }(mp_take_c<mp_list<decltype(args)...>, N>{});
}

https://godbolt.org/z/zEM1eGqxK

template<std::size_t> struct  Any
{
    template<typename T > constexpr Any(T){}
};
template<auto N>
constexpr auto nth_element( auto ...  args )
{
  return [&]<std::size_t... Ns>(std::index_sequence<Ns...>) {
    return [](Any<Ns> ..., auto nth, auto ... ) {
      return nth;
    }(args...);
  }(std::make_index_sequence<N>{});
}

https://godbolt.org/z/3471fcrqG