1
0
forked from Alepha/Alepha

Merge branch 'capabilities-rewrite'

This commit is contained in:
2024-01-27 05:14:21 -05:00
9 changed files with 134 additions and 125 deletions

View File

@ -235,7 +235,7 @@ namespace Alepha::Hydrogen ::detail:: Buffer_m
struct BufferModel_capability {}; struct BufferModel_capability {};
template< typename T > template< typename T >
concept UndecayedBufferModelable= Capability< T, BufferModel_capability >; concept UndecayedBufferModelable= HasCapability< T, BufferModel_capability >;
template< typename T > template< typename T >
concept BufferModelable= UndecayedBufferModelable< std::decay_t< T > >; concept BufferModelable= UndecayedBufferModelable< std::decay_t< T > >;

View File

@ -39,6 +39,7 @@ add_subdirectory( Thread.test )
add_subdirectory( assertion.test ) add_subdirectory( assertion.test )
add_subdirectory( Constness.test ) add_subdirectory( Constness.test )
add_subdirectory( Blob.test ) add_subdirectory( Blob.test )
add_subdirectory( Capabilities.test )
# Sample applications # Sample applications
add_executable( example example.cc ) add_executable( example example.cc )

View File

@ -4,8 +4,8 @@ static_assert( __cplusplus > 2020'99 );
#include <Alepha/Alepha.h> #include <Alepha/Alepha.h>
#include <Alepha/Meta/find.h> #include <Alepha/type_lisp.h>
#include <Alepha/Meta/type_value.h> #include <Alepha/Concepts.h>
namespace Alepha::Hydrogen namespace Alepha::Hydrogen
{ {
@ -15,124 +15,93 @@ namespace Alepha::Hydrogen
{ {
inline namespace exports inline namespace exports
{ {
template< typename ... capabilities > template< typename ... List >
struct Capabilities; struct Capabilities;
template< typename T, typename cap >
struct has_capability_s; //: 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 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 > template< typename T >
struct is_capability_list_s : std::false_type {}; using extract_capability_list_t= typename extract_capability_list< T >::type;
template< typename ... >
struct extract_capability_lists;
template< typename ... Args > template< typename ... Args >
struct is_capability_list_s< Capabilities< Args... > > : std::true_type {}; using extract_capability_lists_t= typename extract_capability_lists< Args... >::type;
inline constexpr Meta::trait< is_capability_list_s > is_capability_list; template< typename Arg >
struct extract_capability_lists< Arg >
template< typename T >
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 >
consteval bool
has_cap_in_capability_base( const Meta::type_value< Capabilities< Caps... > > &, Meta::type_value< Cap > cap )
{ {
Meta::Container::vector< Caps... > types; using type= extract_capability_list_t< Arg >;
using std::begin, std::end;
return Meta::find_if( begin( types ), end( types ), Meta::bind1st( Meta::is_base_of, cap ) );
}
template< typename Left, typename Cap >
constexpr bool
has_cap_in_capability_base( const Left &, Meta::type_value< Cap > cap )
{
throw "Unevaluated";
return false;
}
template< typename Cap, typename ... TParams >
consteval bool
has_cap( const Meta::Container::vector< TParams... > &types, Meta::type_value< Cap > cap )
{
bool rv= 0;
template_for( types ) <=[&]
( const auto 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 > template< typename Arg, typename ... Args >
consteval bool struct extract_capability_lists< Arg, Args... >
has_cap( const Meta::type_value< Class< TParams... > > &, Meta::type_value< Cap > cap )
{ {
return has_cap( Meta::Container::vector< TParams... >{}, cap ); using type= list_cat_t< extract_capability_list_t< Arg >, extract_capability_lists_t< Args... > >;
} };
template< typename Type, typename Cap > template
consteval bool <
has_cap( const Meta::type_value< Type > &, Meta::type_value< Cap > ) template< typename ... > class Basis,
{ typename ... Args
return false; >
} extract_capability_lists_t< Args... >
get_capability_list( Basis< Args... > );
namespace exports namespace exports
{ {
template< typename T, typename cap > template< typename T, typename Capability >
constexpr bool has_capability_v= concept HasCapability= false
std::is_base_of_v< cap, T > or DerivedFrom< T, Capability >
or or CapabilityInList< Capability, decltype( get_capability_list( std::declval< const T & >() ) ) >
has_cap( Meta::type_value< T >{}, Meta::type_value< cap >{} ); ;
template< typename T, typename cap > template< typename T, typename Capability >
struct has_capability_s : std::bool_constant< has_capability_v< T, cap > > {}; concept Capable= HasCapability< T, Capability >;
inline constexpr Meta::trait< has_capability_s > has_capability; template< typename T, typename Cap >
concept Capability= HasCapability< T, Cap >;
template< typename T, typename capability >
concept Capability= has_capability_v< T, capability >;
} }
struct capability_demo {};
struct missing_capability_demo {};
template< typename= Capabilities< capability_demo > >
struct Capable_base {};
using Capable= Capable_base<>;
static_assert( Capability< Capable, capability_demo > == true );
static_assert( Capability< Capable, missing_capability_demo > == false );
template< Capability< missing_capability_demo > C > void f( C ) {}
} }
namespace exports::Capabilities_m namespace exports::Capabilities_m

27
Capabilities.test/0.cc Normal file
View File

@ -0,0 +1,27 @@
static_assert( __cplusplus > 2020'99 );
#include "../Capabilities.h"
#include <Alepha/Testing/test.h>
#include <Alepha/Testing/TableTest.h>
namespace
{
using namespace Alepha::exports::Capabilities_m;
struct capability_demo {};
struct missing_capability_demo {};
template< typename= Capabilities< capability_demo > >
struct Example_base {};
using Example= Example_base<>;
static_assert( HasCapability< Example, capability_demo > == true );
static_assert( HasCapability< Example, missing_capability_demo > == false );
template< HasCapability< missing_capability_demo > C >
void f( C ) {}
}
static auto init= Alepha::Utility::enroll <=[]
{
};

View File

@ -0,0 +1 @@
unit_test( 0 )

View File

@ -28,16 +28,10 @@ namespace Alepha::Hydrogen
namespace exports namespace exports
{ {
using detail::comparisons_m::comparable; using detail::comparisons_m::comparable;
inline constexpr Meta::type_value< comparable > comparable_capability;
} }
template< typename T > template< typename T >
constexpr bool has_comparable_capability_v= has_capability( Meta::type_value< std::decay_t< T > >{}, comparable_capability ); constexpr bool has_comparable_capability_v= HasCapability< std::decay_t< T >, comparable >;
template< typename T >
struct has_comparable_capability_s : std::bool_constant< has_comparable_capability_v< T > > {};
inline constexpr Meta::trait< has_comparable_capability_s > has_comparable_capability;
// Spaceship lens support // Spaceship lens support
@ -54,7 +48,7 @@ namespace Alepha::Hydrogen
template template
< <
typename T, typename T,
typename= std::enable_if_t< has_comparable_capability( Meta::type_value< T >{} ) >, typename= std::enable_if_t< has_comparable_capability_v< T > >,
typename= std::enable_if_t< has_spaceship_lens_member_v< T > >, typename= std::enable_if_t< has_spaceship_lens_member_v< T > >,
overload< __LINE__ > = nullptr overload< __LINE__ > = nullptr
> >

View File

@ -6,6 +6,9 @@ static_assert( __cplusplus > 2020'99 );
#include <Alepha/Testing/TableTest.h> #include <Alepha/Testing/TableTest.h>
#include <Alepha/Utility/evaluation_helpers.h> #include <Alepha/Utility/evaluation_helpers.h>
#include <Alepha/Meta/find.h>
#include <Alepha/Meta/Container/vector.h>
namespace namespace
{ {
using Alepha::Hydrogen::exports::types_m::argcnt_t; using Alepha::Hydrogen::exports::types_m::argcnt_t;
@ -15,12 +18,14 @@ namespace
using namespace Alepha::Hydrogen::exports::comparisons_m; using namespace Alepha::Hydrogen::exports::comparisons_m;
using namespace Alepha::Hydrogen::exports::Capabilities_m; using namespace Alepha::Hydrogen::exports::Capabilities_m;
struct blast {};
template template
< <
typename= int, typename= int,
typename= Capabilities< comparable >, typename= Capabilities< blast >,
typename= float, typename= float,
typename= Capabilities< short > typename= Capabilities< comparable >
> >
struct Date_core struct Date_core
{ {
@ -43,8 +48,9 @@ namespace
static_assert( Meta::find_if( begin( vec ), end( vec ), Meta::bind1st( Meta::is_same, Meta::type_value< int >{} ) ) ); static_assert( Meta::find_if( begin( vec ), end( vec ), Meta::bind1st( Meta::is_same, Meta::type_value< int >{} ) ) );
static_assert( not Meta::find_if( begin( vec ), end( vec ), Meta::bind1st( Meta::is_same, Meta::type_value< double >{} ) ) ); static_assert( not Meta::find_if( begin( vec ), end( vec ), Meta::bind1st( Meta::is_same, Meta::type_value< double >{} ) ) );
static_assert( detail::is_capability_list_v< Capabilities< comparable > > ); //static_assert( detail::is_capability_list_v< Capabilities< comparable > > );
static_assert( Alepha::has_capability( Meta::type_value< Date >{}, comparable_capability ) ); static_assert( Alepha::HasCapability< Date, Alepha::comparable > );
static_assert( Alepha::HasCapability< Date, blast > );
template< template< typename > class op, typename T > template< template< typename > class op, typename T >
constexpr bool constexpr bool

View File

@ -79,7 +79,7 @@ namespace Alepha::Hydrogen ::detail:: swappable_m
}; };
template< typename T > template< typename T >
concept MemberSwapLensable= Capability< T, swappable > or HasMemberSwapLens< T >; concept MemberSwapLensable= HasCapability< T, swappable > or HasMemberSwapLens< T >;
template< MemberSwapLensable T > template< MemberSwapLensable T >
constexpr decltype( auto ) constexpr decltype( auto )
@ -96,7 +96,7 @@ namespace Alepha::Hydrogen ::detail:: swappable_m
}; };
template< typename T > template< typename T >
concept SwapLensable= Capability< T, swappable > and SupportsSwapLens< T >; concept SwapLensable= HasCapability< T, swappable > and SupportsSwapLens< T >;
// To compute the noexceptness of a swap expression, we // To compute the noexceptness of a swap expression, we

View File

@ -5,6 +5,7 @@ static_assert( __cplusplus > 2020'99 );
#include <Alepha/Alepha.h> #include <Alepha/Alepha.h>
#include <type_traits> #include <type_traits>
#include <tuple>
namespace Alepha::Hydrogen ::detail:: type_lisp_m namespace Alepha::Hydrogen ::detail:: type_lisp_m
{ {
@ -74,18 +75,28 @@ namespace Alepha::Hydrogen ::detail:: type_lisp_m
using cdr_t= typename cdr_impl< List >::type; using cdr_t= typename cdr_impl< List >::type;
} }
template< typename List, typename Element >
struct list_contains
{
static const bool value= std::is_same_v< Element, car_t< List > > or list_contains< cdr_t< List >, Element >::value;
};
template< typename Element >
struct list_contains< Nil, Element > : std::false_type {};
namespace exports namespace exports
{ {
template< typename List, typename Element > template< typename List, typename Element >
constexpr bool list_contains_v= constexpr bool list_contains_v= list_contains< List, Element >::value;
std::is_same_v< Element, car_t< List > >
or
list_contains_v< cdr_t< List >, Element >;
template< typename Element >
constexpr bool list_contains_v< Nil, Element >{};
} }
struct Alpha;
struct Beta;
struct Gamma;
static_assert( list_contains_v< TypeList< Alpha, Beta >, Alpha > );
static_assert( list_contains_v< TypeList< Alpha, Beta >, Beta > );
static_assert( not list_contains_v< TypeList< Alpha, Beta >, Gamma > );
template< typename Element, typename List > template< typename Element, typename List >
struct cons; struct cons;