// file: type_list.hpp // author: Filip Roséen // source: http://b.atch.se/posts/constexpr-meta-container #ifndef ATCH_TYPE_LIST_HPP #define ATCH_TYPE_LIST_HPP #include #include namespace atch { template using ic = std::integral_constant; template using iseq = std::index_sequence; template using make_iseq = std::make_index_sequence; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct type_list { using size_type = std::size_t; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static constexpr size_type size () { return sizeof... (Ts); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct at { template struct wrapper { using result = T; }; template struct access_helper { using result = typename std::conditional_t< (Idx == N), wrapper, access_helper >::result; }; using result = typename access_helper<0, Ts..., void>::result; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct push { using result = type_list; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct set { struct wrapper { using result = U; }; template struct access_helper { using result = typename std::conditional_t, wrapper>::result; }; template static auto set_helper (iseq) -> type_list::result...> { } using result = decltype (set_helper (make_iseq ())); }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - struct init { template static auto helper (iseq) -> type_list::result...> ; using result = decltype (helper (make_iseq ())); }; }; } /* namespace atch */ #endif /* include guard */ // file: meta_counter.hpp // author: Filip Roséen // source: http://b.atch.se/posts/constexpr-meta-container #ifndef ATCH_META_COUNTER_HPP #define ATCH_META_COUNTER_HPP #include namespace atch { namespace { template struct meta_counter { using size_type = std::size_t; template struct ident { friend constexpr size_type adl_lookup (ident); static constexpr size_type value = N; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct writer { friend constexpr size_type adl_lookup (Ident) { return Ident::value; } static constexpr size_type value = Ident::value; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template ()))?+1:-1]> static constexpr size_type value_reader (int, ident) { return N; } template static constexpr size_type value_reader (float, ident, size_type R = value_reader (0, ident ())) { return R; } static constexpr size_type value_reader (float, ident<0>) { return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template static constexpr size_type value (size_type R = value_reader (0, ident ())) { return R; } template static constexpr size_type next (size_type R = writer>::value) { return R; } }; }} #endif /* include guard */ // file: meta_list.hpp // author: Filip Roséen // source: http://b.atch.se/posts/constexpr-meta-container #ifndef ATCH_META_LIST_HPP #define ATCH_META_LIST_HPP #include namespace atch { namespace { template struct meta_list { using counter = atch::meta_counter>; using size_type = typename counter::size_type; template struct ident { friend auto adl_lookup (ident); friend auto adl_lookup (ident) { return atch::type_list<> {}; } static constexpr size_type value = N; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template struct writer { friend auto adl_lookup (ident) { return Value {}; } static constexpr size_type value = Ident::value; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template< class State, class H = meta_list, size_type C = H::counter::next (), class Ident = typename H::template ident > static constexpr size_type push_state (size_type R = writer::value) { return R; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template< class H = meta_list, size_type N = H::counter::value ()> using value_ident = typename H::template ident; template< class H = meta_list, class Ident = typename H::template value_ident<> > using value = decltype (adl_lookup (Ident ())); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template static constexpr void push ( size_type = push_state< typename H::template value<>::template push::result > () ) {} template static constexpr void pop ( size_type = push_state< typename H::template value<>::init::result > () ) {} template static constexpr void set ( size_type = push_state< typename H::template value<>::template set::result > () ) {} }; }} #endif /* include guard */ // file: main.cpp // author: Filip Roséen // source: http://b.atch.se/posts/constexpr-meta-container #include // std::is_same int main () { using LX = atch::meta_list; LX::push (); LX::set<0, class Hello> (); LX::set<2, class World> (); LX::pop (); LX::value<> x; // type_list static_assert ( std::is_same< atch::type_list, LX::value<> >::value, "try again" ); }