forked from Alepha/Alepha
Well this whole () base TMP experiment kinda works.
It's a lot of heavy lifting. I'm not sure it actually adds any useful value yet, but I'll continue to play with it. It is nice that we can *sometimes* use loops. Sometimes we can't though. And we have to make some blind-corner evaluations that throw dummy failures to keep the compiler from complaining about missing cases -- despite the fact that they;ll never be reached at compiletime. (Runtime evaluation could be different, of course.) I think, perhaps, a universal representation of a dereferenced iterator might solve some of this, but I also don't want to sink too much effort into this, despite how much fun I'm having.
This commit is contained in:
@ -5,7 +5,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||
#include <Alepha/Alepha.h>
|
||||
|
||||
#include <Alepha/Meta/find.h>
|
||||
#include <Alepha/Stud/type_traits.h>
|
||||
#include <Alepha/Meta/type_value.h>
|
||||
|
||||
namespace Alepha::Hydrogen
|
||||
{
|
||||
@ -19,7 +19,7 @@ namespace Alepha::Hydrogen
|
||||
struct Capabilities;
|
||||
|
||||
template< typename T, typename cap >
|
||||
struct has_capability; //: std::is_base_of< cap, T > {};
|
||||
struct has_capability_s; //: std::is_base_of< cap, T > {};
|
||||
|
||||
|
||||
#if 0
|
||||
@ -50,58 +50,68 @@ namespace Alepha::Hydrogen
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
struct is_capability_list : std::false_type {};
|
||||
struct is_capability_list_s : std::false_type {};
|
||||
|
||||
template< typename ... Args >
|
||||
struct is_capability_list< Capabilities< Args... > > : std::true_type {};
|
||||
struct is_capability_list_s< Capabilities< Args... > > : std::true_type {};
|
||||
|
||||
inline constexpr Meta::trait< is_capability_list_s > is_capability_list;
|
||||
|
||||
template< typename T >
|
||||
constexpr bool is_capability_list_v= is_capability_list< T >::value;
|
||||
constexpr bool is_capability_list_v= is_capability_list( Meta::type_value< T >{} );
|
||||
|
||||
|
||||
template< template< typename ... > class ... HigherKinds >
|
||||
struct higher_kind_tuple {};
|
||||
|
||||
template< typename cap, typename ... Caps >
|
||||
constexpr auto
|
||||
has_cap( const Stud::type_identity< Capabilities< Caps... > > & )
|
||||
template< typename Cap, typename ... Caps >
|
||||
constexpr bool
|
||||
has_cap_in_capability_base( const Meta::type_value< Capabilities< Caps... > > &, Meta::type_value< Cap > cap )
|
||||
{
|
||||
return Meta::find_if< Meta::bind1st< std::is_base_of, cap >, Meta::Container::vector< Caps... > >{};
|
||||
Meta::Container::vector< Caps... > types;
|
||||
using std::begin, std::end;
|
||||
return Meta::find_if( begin( types ), end( types ), Meta::bind1st( Meta::is_base_of, cap ) );
|
||||
}
|
||||
|
||||
template< typename cap >
|
||||
constexpr std::false_type has_cap( const Meta::Container::vector<> & ) { return {}; }
|
||||
|
||||
template< typename cap, typename First, typename ... TParams >
|
||||
constexpr auto
|
||||
has_cap( const Meta::Container::vector< First, TParams... > & )
|
||||
template< typename Left, typename Cap >
|
||||
constexpr bool
|
||||
has_cap_in_capability_base( const Left &, Meta::type_value< Cap > cap )
|
||||
{
|
||||
using depth_type= decltype( has_cap< cap >( Meta::Container::vector< TParams... >{} ) );
|
||||
if constexpr( is_capability_list_v< First > )
|
||||
throw "Unevaluated";
|
||||
}
|
||||
|
||||
template< typename Cap, typename ... TParams >
|
||||
constexpr bool
|
||||
has_cap( const Meta::Container::vector< TParams... > &types, Meta::type_value< Cap > cap )
|
||||
{
|
||||
bool rv= 0;
|
||||
template_for( types ) <=[&]
|
||||
( const auto type )
|
||||
{
|
||||
using bool_type= decltype( has_cap< cap >( Stud::type_identity< First >() ) );
|
||||
if constexpr( bool_type::value )
|
||||
{
|
||||
return std::bool_constant< bool_type::value >{};
|
||||
}
|
||||
else return depth_type{};
|
||||
}
|
||||
else return depth_type{};
|
||||
if( is_capability_list( type ) and has_cap_in_capability_base( type, cap ) ) rv= true;
|
||||
};
|
||||
return rv;
|
||||
}
|
||||
|
||||
template< typename cap, template< typename ... > class Class, typename ... TParams >
|
||||
constexpr auto
|
||||
has_cap( const Class< TParams... > & )
|
||||
template< typename Cap, template< typename ... > class Class, typename ... TParams >
|
||||
constexpr bool
|
||||
has_cap( const Meta::type_value< Class< TParams... > > &, Meta::type_value< Cap > cap )
|
||||
{
|
||||
return has_cap< cap >( Meta::Container::vector< TParams... >{} );
|
||||
return has_cap( Meta::Container::vector< TParams... >{}, cap );
|
||||
}
|
||||
|
||||
namespace exports
|
||||
{
|
||||
template< typename T, typename cap >
|
||||
constexpr bool has_capability_v= std::is_base_of_v< cap, T > or decltype( has_cap< cap >( std::declval< T >() ) )::value;
|
||||
constexpr bool has_capability_v=
|
||||
std::is_base_of_v< cap, T >
|
||||
or
|
||||
has_cap( Meta::type_value< T >{}, Meta::type_value< cap >{} );
|
||||
|
||||
template< typename T, typename cap >
|
||||
struct has_capability : std::bool_constant< has_capability_v< T, cap > > {};
|
||||
struct has_capability_s : std::bool_constant< has_capability_v< T, cap > > {};
|
||||
|
||||
inline constexpr Meta::trait< has_capability_s > has_capability;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user