書き初め
constexpr lambdaが使えるってことは?ということで思いついたネタを。 とりあえずclangさんでは動いてしまった。gccさんは置いてけぼりです。 wandbox.org
proof of conceptなので、必要なオーバーロード全然なかったり勝手にconstついたりする気がするので注意。
#include <iostream> #include <utility> static constexpr auto stack = [](auto... xs) constexpr { return [=](auto access) { return access(xs...); }; }; template <std::size_t N> struct popper {}; template <typename Type> struct helper { Type data; template <typename T> static constexpr auto make_helper(T&& arg) { return helper<std::decay_t<T>>(std::forward<T>(arg)); } static constexpr auto push = [](auto xs, auto x) constexpr { return xs([=](auto... z) { return [=](auto access) { return access(x, z...); }; }); }; static constexpr auto pop = [](auto xs) constexpr { return xs([=](auto, auto... z) { return [=](auto access) { return access(z...); }; }); }; template <typename T> constexpr helper(T&& arg) : data(std::forward<T>(arg)) {}; template <typename U> constexpr auto operator +(const U& rhs) const { return helper<Type>::make_helper(push(this->data, rhs.data)); } template <typename U> constexpr auto operator -(const U&) const { return helper<Type>::make_helper(pop(this->data)); } }; static constexpr auto top = [](auto xs) constexpr { return xs.data([=](auto v, auto...) { return v; }); }; template <typename T> static constexpr auto make_helper(T&& arg) { return helper<std::decay_t<T>>(std::forward<T>(arg)); } template <typename... Types> struct tuple { decltype((make_helper(stack()) + ... + make_helper(std::declval<Types>()))) data; template <typename... Ts> constexpr tuple(Ts&&... args) : data((make_helper(stack()) + ... + make_helper(std::forward<Ts&&>(args)))) {} }; template <typename... Types, std::size_t... Indices> constexpr auto get_impl(const tuple<Types...>& t, std::index_sequence<Indices...>) { return (t.data - ... - make_helper(popper<Indices>{})); } template <std::size_t N, typename... Types> constexpr auto get(const tuple<Types...>& t) { static_assert(sizeof...(Types) > 0); return top(get_impl(t, std::make_index_sequence<(sizeof...(Types) - 1) - N>{})); } int main() { constexpr tuple<int, char, double, bool> t(1, 'a', 3.14, true); static_assert(get<0>(t) == 1); static_assert(get<1>(t) == 'a'); static_assert(get<2>(t) == 3.14); static_assert(get<3>(t) == true); }