forked from Alepha/Alepha
209 lines
4.4 KiB
C++
209 lines
4.4 KiB
C++
static_assert( __cplusplus > 2020'99 );
|
|
|
|
#pragma once
|
|
|
|
#include <Alepha/Alepha.h>
|
|
|
|
#include <type_traits>
|
|
#include <tuple>
|
|
|
|
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;
|
|
}
|
|
|