static_assert( __cplusplus > 2020'99 ); #pragma once #include #include #include namespace Alepha::Hydrogen ::detail:: type_lisp_m { inline namespace exports {} namespace exports { template< typename ... > struct TypeList {}; using Nil= TypeList<>; template< typename T > constexpr bool is_nil_v= std::is_same_v< T, Nil >; } template< typename T > constexpr bool is_type_list_v= false; template< typename ... Args > constexpr bool is_type_list_v< TypeList< Args... > >{ true }; namespace exports { template< typename Type > concept TypeListType= is_type_list_v< Type >; } template< typename T > struct tuple_from_list; namespace exports { template< typename List > using tuple_from_list_t= typename tuple_from_list< List >::type; } template< typename ... Members > struct tuple_from_list< TypeList< Members... > > { using type= std::tuple< Members... >; }; template< TypeListType > struct list_size; template< typename ... Members > struct list_size< TypeList< Members... > > { static const std::size_t value= sizeof...( Members ); }; namespace exports { template< TypeListType List > constexpr std::size_t list_size_v= list_size< List >::value; } template< typename List > struct car_impl { using type= Nil; }; template< typename Arg0, typename ... Args > struct car_impl< TypeList< Arg0, Args... > > { using type= Arg0; }; template< typename List > struct cdr_impl { using type= Nil; }; template< typename Arg0, typename ... Args > struct cdr_impl< TypeList< Arg0, Args... > > { using type= TypeList< Args... >; }; namespace exports { template< typename List > using car_t= typename car_impl< List >::type; template< typename List > using cdr_t= typename cdr_impl< List >::type; } template< typename List, typename Element > struct list_contains { static const bool value= std::is_same_v< Element, car_t< List > > or list_contains< cdr_t< List >, Element >::value; }; template< typename Element > struct list_contains< Nil, Element > : std::false_type {}; namespace exports { template< typename List, typename Element > constexpr bool list_contains_v= list_contains< List, Element >::value; } struct Alpha; struct Beta; struct Gamma; static_assert( list_contains_v< TypeList< Alpha, Beta >, Alpha > ); static_assert( list_contains_v< TypeList< Alpha, Beta >, Beta > ); static_assert( not list_contains_v< TypeList< Alpha, Beta >, Gamma > ); template< typename Element, typename List > struct cons; template< typename Element, typename ... Members > struct cons< Element, TypeList< Members... > > { using type= TypeList< Element, Members... >; }; namespace exports { template< typename Element, typename List > using cons_t= typename cons< Element, List >::type; } template< typename Tuple > struct list_from_tuple; namespace exports { template< typename Tuple > using list_from_tuple_t= typename list_from_tuple< Tuple >::type; } template< typename ... Members > struct list_from_tuple< std::tuple< Members... > > { using type= TypeList< Members... >; }; template< typename Left, typename Right > struct list_cat; namespace exports { template< typename Left, typename Right > using list_cat_t= typename list_cat< Left, Right >::type; } template< typename ... LeftArgs, typename ... RightArgs > struct list_cat< TypeList< LeftArgs... >, TypeList< RightArgs... > > { using type= TypeList< LeftArgs..., RightArgs... >; }; template< typename Item, std::size_t count > struct repeat; namespace exports { template< typename Item, std::size_t count > using repeat_t= typename repeat< Item, count >::type; } template< typename Item, std::size_t count > struct repeat { using type= cons_t< Item, repeat_t< Item, count - 1 > >; }; template< typename Item > struct repeat< Item, 0 > { using type= Nil; }; template< TypeListType list > struct strip_last; namespace exports { template< typename list > using strip_last_t= tuple_from_list_t< typename strip_last< list_from_tuple_t< list > >::type >; } template< TypeListType list > struct strip_last { using type= cons_t< car_t< list >, typename strip_last< cdr_t< list > >::type >; }; template< typename last > struct strip_last< TypeList< last > > { using type= Nil; }; } namespace Alepha::Hydrogen::inline exports::inline type_lisp_m { using namespace detail::type_lisp_m::exports; }