1
0
forked from Alepha/Alepha
Files
Alepha/Capabilities.h

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;
}
}