1
0
forked from Alepha/Alepha

I added the lens-based comparison code.

The metaprogramming is still based upon the angle-bracket
type-form.  Now to rewrite it in terms of the constexpr systems.
This commit is contained in:
2021-10-25 02:02:12 -04:00
parent 3c11d6af74
commit f2ae99f648
4 changed files with 616 additions and 0 deletions

112
Capabilities.h Normal file
View File

@ -0,0 +1,112 @@
static_assert( __cplusplus > 201700, "C++17 Required" );
#pragma once
#include <Alepha/Alepha.h>
#include <Alepha/Meta/find.h>
#include <Alepha/Stud/type_traits.h>
namespace Alepha::Hydrogen
{
inline namespace exports { inline namespace capabilities {} }
namespace detail::capabilities
{
inline namespace exports
{
template< typename ... capabilities >
struct Capabilities;
template< typename T, typename cap >
struct has_capability; //: std::is_base_of< cap, T > {};
#if 0
template< template< typename ... > class Type, typename ... Caps, typename cap >
struct has_capability< Type< Capabilities< Caps... > >, cap >
{
using T= Type< Capabilities< Caps... > >;
static constexpr bool value= Meta::find_in_tuple_v< cap, std::tuple< Caps... > > or std::is_base_of_v< cap, T >;
using type= has_capability;
};
template< template< typename ... > class Type, typename ... Back, typename ... Caps, typename cap >
struct has_capability< Type< Capabilities< Caps... >, Back... >, cap >
{
using T= Type< Capabilities< Caps... >, Back... >;
static constexpr bool value= Meta::find_in_tuple_v< cap, std::tuple< Caps... > > or std::is_base_of_v< cap, T >;
using type= has_capability;
};
template< template< typename ... > class Type, typename ... Front, typename ... Caps, typename cap >
struct has_capability< Type< Front..., Capabilities< Caps... > >, cap >
{
using T= Type< Front..., Capabilities< Caps... > >;
static constexpr bool value= Meta::find_in_tuple_v< cap, std::tuple< Caps... > > or std::is_base_of_v< cap, T >;
using type= has_capability;
};
#endif
}
template< typename T >
struct is_capability_list : std::false_type {};
template< typename ... Args >
struct is_capability_list< Capabilities< Args... > > : std::true_type {};
template< typename T >
constexpr bool is_capability_list_v= is_capability_list< T >::value;
template< template< typename ... > class ... HigherKinds >
struct higher_kind_tuple {};
template< typename cap, typename ... Caps >
constexpr auto
has_cap( const Stud::type_identity< Capabilities< Caps... > > & )
{
return Meta::find_if< Meta::bind1st< std::is_base_of, cap >, Meta::list< Caps... > >{};
}
template< typename cap >
constexpr std::false_type has_cap( const Meta::list<> & ) { return {}; }
template< typename cap, typename First, typename ... TParams >
constexpr auto
has_cap( const Meta::list< First, TParams... > & )
{
using depth_type= decltype( has_cap< cap >( Meta::list< TParams... >{} ) );
if constexpr( is_capability_list_v< First > )
{
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{};
}
template< typename cap, template< typename ... > class Class, typename ... TParams >
constexpr auto
has_cap( const Class< TParams... > & )
{
return has_cap< cap >( Meta::list< TParams... >{} );
}
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;
template< typename T, typename cap >
struct has_capability : std::bool_constant< has_capability_v< T, cap > > {};
}
}
namespace exports::capabilities
{
using namespace detail::capabilities::exports;
}
}