forked from Alepha/Alepha
112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
static_assert( __cplusplus > 2020'99 );
|
|
|
|
#pragma once
|
|
|
|
#include <Alepha/Alepha.h>
|
|
|
|
#include <Alepha/type_lisp.h>
|
|
#include <Alepha/Concepts.h>
|
|
|
|
namespace Alepha::Hydrogen
|
|
{
|
|
inline namespace exports { inline namespace Capabilities_m {} }
|
|
|
|
namespace detail::Capabilities_m
|
|
{
|
|
inline namespace exports
|
|
{
|
|
template< typename ... List >
|
|
struct Capabilities;
|
|
}
|
|
|
|
template< typename List, typename Capability >
|
|
struct list_matches;
|
|
|
|
template< typename List, typename Capability >
|
|
constexpr bool list_matches_v= list_matches< List, Capability >::value;
|
|
|
|
template< typename Capability >
|
|
struct list_matches< Nil, Capability > : std::false_type {};
|
|
|
|
template< typename List, typename Capability >
|
|
struct list_matches
|
|
{
|
|
static constexpr bool value= false
|
|
or DerivedFrom< car_t< List >, Capability >
|
|
or list_matches_v< cdr_t< List >, Capability >
|
|
;
|
|
};
|
|
|
|
|
|
template< typename Capability, typename List >
|
|
concept CapabilityInList= list_matches_v< List, Capability >;
|
|
|
|
Nil get_capability_list( ... );
|
|
|
|
template< typename ... List >
|
|
struct exports::Capabilities
|
|
{
|
|
friend constexpr TypeList< List... >
|
|
get_capability_list( const auto & );
|
|
};
|
|
|
|
template< typename >
|
|
struct extract_capability_list { using type= Nil; };
|
|
|
|
template< typename ... Caps >
|
|
struct extract_capability_list< Capabilities< Caps... > >
|
|
{
|
|
using type= TypeList< Caps... >;
|
|
};
|
|
|
|
template< typename T >
|
|
using extract_capability_list_t= typename extract_capability_list< T >::type;
|
|
|
|
template< typename ... >
|
|
struct extract_capability_lists;
|
|
|
|
template< typename ... Args >
|
|
using extract_capability_lists_t= typename extract_capability_lists< Args... >::type;
|
|
|
|
template< typename Arg >
|
|
struct extract_capability_lists< Arg >
|
|
{
|
|
using type= extract_capability_list_t< Arg >;
|
|
};
|
|
|
|
template< typename Arg, typename ... Args >
|
|
struct extract_capability_lists< Arg, Args... >
|
|
{
|
|
using type= list_cat_t< extract_capability_list_t< Arg >, extract_capability_lists_t< Args... > >;
|
|
};
|
|
|
|
template
|
|
<
|
|
template< typename ... > class Basis,
|
|
typename ... Args
|
|
>
|
|
extract_capability_lists_t< Args... >
|
|
get_capability_list( Basis< Args... > );
|
|
|
|
namespace exports
|
|
{
|
|
template< typename T, typename 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 >;
|
|
}
|
|
}
|
|
|
|
namespace exports::Capabilities_m
|
|
{
|
|
using namespace detail::Capabilities_m::exports;
|
|
}
|
|
}
|