forked from Alepha/Alepha
I think this makes capabilities much simpler and more reliable.
But the capabilities are now limited to a single param -- Time to change that?
This commit is contained in:
@ -15,76 +15,54 @@ namespace Alepha::Hydrogen
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
template< typename ... capabilities >
|
||||
template< typename ... List >
|
||||
struct Capabilities;
|
||||
}
|
||||
|
||||
struct CapabilityBase {};
|
||||
template< typename ... capabilities >
|
||||
struct exports::Capabilities : CapabilityBase {};
|
||||
template< typename List, typename Capability >
|
||||
struct list_matches;
|
||||
|
||||
template< typename T >
|
||||
concept CapabilityList= DerivedFrom< T, CapabilityBase >;
|
||||
|
||||
|
||||
template< typename T >
|
||||
constexpr bool is_capability_list_v= false;
|
||||
|
||||
template< typename ... Args >
|
||||
constexpr bool is_capability_list_v< Capabilities< Args... > > { true };
|
||||
|
||||
template< typename Capability, TypeListType List >
|
||||
constexpr bool has_capability_in_list_v= false
|
||||
or SameAs< car_t< List >, Capability >
|
||||
or DerivedFrom< car_t< List >, Capability >
|
||||
or has_capability_in_list_v< Capability, cdr_t< List > >;
|
||||
template< typename List, typename Capability >
|
||||
constexpr bool list_matches_v= list_matches< List, Capability >::value;
|
||||
|
||||
template< typename Capability >
|
||||
constexpr bool has_capability_in_list_v< Capability, Nil > {};
|
||||
struct list_matches< Nil, Capability > : std::false_type {};
|
||||
|
||||
template< typename ... Args >
|
||||
constexpr TypeListType auto
|
||||
extract_list( const Capabilities< Args... > & )
|
||||
template< typename List, typename Capability >
|
||||
struct list_matches
|
||||
{
|
||||
return TypeList< Args... >{};
|
||||
}
|
||||
|
||||
template< typename T > struct get_capability_list { using type= Nil; };
|
||||
|
||||
template< CapabilityList T >
|
||||
struct get_capability_list< T >
|
||||
{
|
||||
using type= decltype( extract_list( std::declval< const T & >() ) );
|
||||
static constexpr bool value= false
|
||||
or DerivedFrom< car_t< List >, Capability >
|
||||
or list_matches_v< cdr_t< List >, Capability >
|
||||
;
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
<
|
||||
template< typename ... > class Built,
|
||||
typename ... LeftArgs,
|
||||
typename ... RightArgs,
|
||||
CapabilityList List
|
||||
>
|
||||
struct get_capability_list< Built< LeftArgs..., List, RightArgs... > >
|
||||
template< typename Capability, typename List >
|
||||
concept CapabilityInList= list_matches_v< List, Capability >;
|
||||
|
||||
Nil get_capability_list( ... );
|
||||
|
||||
template< typename ... List >
|
||||
struct exports::Capabilities
|
||||
{
|
||||
using type= typename get_capability_list< List >::type;
|
||||
friend constexpr TypeList< List... >
|
||||
get_capability_list( const auto & );
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
using get_capability_list_t= typename get_capability_list< T >::type;
|
||||
|
||||
namespace exports
|
||||
{
|
||||
template< typename T, typename Capability >
|
||||
constexpr bool has_capability_v=
|
||||
has_capability_in_list_v< Capability, get_capability_list_t< T > >
|
||||
or
|
||||
DerivedFrom< T, Capability >;
|
||||
|
||||
template< typename T, typename Capability >
|
||||
concept HasCapability= has_capability_v< T, Capability >;
|
||||
concept HasCapability= false
|
||||
or DerivedFrom< T, Capability >
|
||||
or CapabilityInList< Capability, decltype( get_capability_list( std::declval< const T & >() ) ) >
|
||||
;
|
||||
|
||||
template< typename T, typename Capability >
|
||||
concept Capable= HasCapability< T, Capability >;
|
||||
|
||||
template< typename T, typename Cap >
|
||||
concept Capability= HasCapability< T, Cap >;
|
||||
}
|
||||
|
||||
struct capability_demo {};
|
||||
@ -92,16 +70,6 @@ namespace Alepha::Hydrogen
|
||||
template< typename= Capabilities< capability_demo > >
|
||||
struct Example_base {};
|
||||
using Example= Example_base<>;
|
||||
static_assert( not DerivedFrom< Example, capability_demo > );
|
||||
static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > );
|
||||
using XXx= get_capability_list_t< Capabilities< capability_demo > >;
|
||||
constexpr XXx qqq= TypeList< capability_demo >{};
|
||||
constexpr TypeList< capability_demo > zzz= get_capability_list_t< Example >{};
|
||||
static_assert( std::is_same_v< get_capability_list_t< Capabilities< capability_demo > >, TypeList< capability_demo > > );
|
||||
static_assert( std::is_same_v< get_capability_list_t< Example >, TypeList< capability_demo > > );
|
||||
static_assert( std::is_same_v< capability_demo, car_t< get_capability_list_t< Example > > > == true );
|
||||
static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > == true );
|
||||
static_assert( has_capability_in_list_v< capability_demo, get_capability_list_t< Example > > == true );
|
||||
static_assert( HasCapability< Example, capability_demo > == true );
|
||||
static_assert( HasCapability< Example, missing_capability_demo > == false );
|
||||
template< HasCapability< missing_capability_demo > C > void f( C ) {}
|
||||
|
Reference in New Issue
Block a user