From e8b41a0116b73f1ca5e333eed677c6112ba259ac Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Fri, 26 Jan 2024 23:17:22 -0500 Subject: [PATCH 1/4] Started a rewrite... but now I'm going to try it with friends? --- Buffer.h | 2 +- Capabilities.h | 154 ++++++++++++++++++++----------------------------- swappable.h | 2 +- 3 files changed, 65 insertions(+), 93 deletions(-) diff --git a/Buffer.h b/Buffer.h index c3d450d..0cb2883 100644 --- a/Buffer.h +++ b/Buffer.h @@ -235,7 +235,7 @@ namespace Alepha::Hydrogen ::detail:: Buffer_m struct BufferModel_capability {}; template< typename T > - concept UndecayedBufferModelable= Capability< T, BufferModel_capability >; + concept UndecayedBufferModelable= HasCapability< T, BufferModel_capability >; template< typename T > concept BufferModelable= UndecayedBufferModelable< std::decay_t< T > >; diff --git a/Capabilities.h b/Capabilities.h index e1b9011..3cc9e8d 100644 --- a/Capabilities.h +++ b/Capabilities.h @@ -4,8 +4,8 @@ static_assert( __cplusplus > 2020'99 ); #include -#include -#include +#include +#include namespace Alepha::Hydrogen { @@ -17,122 +17,94 @@ namespace Alepha::Hydrogen { template< typename ... 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 T > - struct is_capability_list_s : std::false_type {}; - - template< typename ... Args > - struct is_capability_list_s< Capabilities< Args... > > : std::true_type {}; - - inline constexpr Meta::trait< is_capability_list_s > is_capability_list; + struct CapabilityBase {}; + template< typename ... capabilities > + struct exports::Capabilities : CapabilityBase {}; template< typename T > - constexpr bool is_capability_list_v= is_capability_list( Meta::type_value< T >{} ); + concept CapabilityList= DerivedFrom< T, CapabilityBase >; - template< template< typename ... > class ... HigherKinds > - struct higher_kind_tuple {}; + template< typename T > + constexpr bool is_capability_list_v= false; - template< typename Cap, typename ... Caps > - consteval bool - has_cap_in_capability_base( const Meta::type_value< Capabilities< Caps... > > &, Meta::type_value< Cap > cap ) + template< typename ... Args > + constexpr bool is_capability_list_v< Capabilities< Args... > > { true }; + + template< typename Capability, TypeListType List > + constexpr bool has_capability_in_list_v= false + or SameAs< car_t< List >, Capability > + or DerivedFrom< car_t< List >, Capability > + or has_capability_in_list_v< Capability, cdr_t< List > >; + + template< typename Capability > + constexpr bool has_capability_in_list_v< Capability, Nil > {}; + + template< typename ... Args > + constexpr TypeListType auto + extract_list( const Capabilities< Args... > & ) { - 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 ) ); + return TypeList< Args... >{}; } - 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 T > struct get_capability_list { using type= Nil; }; - template< typename Cap, typename ... TParams > - consteval bool - has_cap( const Meta::Container::vector< TParams... > &types, Meta::type_value< Cap > cap ) + template< CapabilityList T > + struct get_capability_list< T > { - 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; - } + using type= decltype( extract_list( std::declval< const T & >() ) ); + }; - template< typename Cap, template< typename ... > class Class, typename ... TParams > - consteval bool - has_cap( const Meta::type_value< Class< TParams... > > &, Meta::type_value< Cap > cap ) + template + < + template< typename ... > class Built, + typename ... LeftArgs, + typename ... RightArgs, + CapabilityList List + > + struct get_capability_list< Built< LeftArgs..., List, RightArgs... > > { - return has_cap( Meta::Container::vector< TParams... >{}, cap ); - } + using type= typename get_capability_list< List >::type; + }; - template< typename Type, typename Cap > - consteval bool - has_cap( const Meta::type_value< Type > &, Meta::type_value< Cap > ) - { - return false; - } + template< typename T > + using get_capability_list_t= typename get_capability_list< T >::type; namespace exports { - template< typename T, typename cap > + template< typename T, typename Capability > constexpr bool has_capability_v= - std::is_base_of_v< cap, T > + has_capability_in_list_v< Capability, get_capability_list_t< T > > or - has_cap( Meta::type_value< T >{}, Meta::type_value< cap >{} ); + DerivedFrom< T, Capability >; - template< typename T, typename cap > - struct has_capability_s : std::bool_constant< has_capability_v< T, cap > > {}; + template< typename T, typename Capability > + concept HasCapability= has_capability_v< T, Capability >; - inline constexpr Meta::trait< has_capability_s > has_capability; - - template< typename T, typename capability > - concept Capability= has_capability_v< T, capability >; + template< typename T, typename Capability > + concept Capable= HasCapability< 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 ) {} + struct Example_base {}; + using Example= Example_base<>; + static_assert( not DerivedFrom< Example, capability_demo > ); + static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > ); + using XXx= get_capability_list_t< Capabilities< capability_demo > >; + constexpr XXx qqq= TypeList< capability_demo >{}; + constexpr TypeList< capability_demo > zzz= get_capability_list_t< Example >{}; + static_assert( std::is_same_v< get_capability_list_t< Capabilities< capability_demo > >, TypeList< capability_demo > > ); + static_assert( std::is_same_v< get_capability_list_t< Example >, TypeList< capability_demo > > ); + static_assert( std::is_same_v< capability_demo, car_t< get_capability_list_t< Example > > > == true ); + static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > == true ); + static_assert( has_capability_in_list_v< capability_demo, get_capability_list_t< Example > > == true ); + static_assert( HasCapability< Example, capability_demo > == true ); + static_assert( HasCapability< Example, missing_capability_demo > == false ); + template< HasCapability< missing_capability_demo > C > void f( C ) {} } namespace exports::Capabilities_m diff --git a/swappable.h b/swappable.h index 36152aa..3e0bb22 100644 --- a/swappable.h +++ b/swappable.h @@ -79,7 +79,7 @@ namespace Alepha::Hydrogen ::detail:: swappable_m }; template< typename T > - concept MemberSwapLensable= Capability< T, swappable > or HasMemberSwapLens< T >; + concept MemberSwapLensable= HasCapability< T, swappable > or HasMemberSwapLens< T >; template< MemberSwapLensable T > constexpr decltype( auto ) From 9c9ed65312c08cf63c84497f50be0f37afc9ea1b Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sat, 27 Jan 2024 04:21:27 -0500 Subject: [PATCH 2/4] I think this makes capabilities much simpler and more reliable. But the capabilities are now limited to a single param -- Time to change that? --- Capabilities.h | 90 ++++++++++++++----------------------------- comparisons.h | 10 +---- comparisons.test/0.cc | 11 ++++-- swappable.h | 2 +- type_lisp.h | 25 ++++++++---- 5 files changed, 57 insertions(+), 81 deletions(-) diff --git a/Capabilities.h b/Capabilities.h index 3cc9e8d..c9ce223 100644 --- a/Capabilities.h +++ b/Capabilities.h @@ -15,76 +15,54 @@ namespace Alepha::Hydrogen { inline namespace exports { - template< typename ... capabilities > + template< typename ... List > struct Capabilities; } - struct CapabilityBase {}; - template< typename ... capabilities > - struct exports::Capabilities : CapabilityBase {}; + template< typename List, typename Capability > + struct list_matches; - template< typename T > - concept CapabilityList= DerivedFrom< T, CapabilityBase >; - - - template< typename T > - constexpr bool is_capability_list_v= false; - - template< typename ... Args > - constexpr bool is_capability_list_v< Capabilities< Args... > > { true }; - - template< typename Capability, TypeListType List > - constexpr bool has_capability_in_list_v= false - or SameAs< car_t< List >, Capability > - or DerivedFrom< car_t< List >, Capability > - or has_capability_in_list_v< Capability, cdr_t< List > >; + template< typename List, typename Capability > + constexpr bool list_matches_v= list_matches< List, Capability >::value; template< typename Capability > - constexpr bool has_capability_in_list_v< Capability, Nil > {}; + struct list_matches< Nil, Capability > : std::false_type {}; - template< typename ... Args > - constexpr TypeListType auto - extract_list( const Capabilities< Args... > & ) + template< typename List, typename Capability > + struct list_matches { - return TypeList< Args... >{}; - } - - template< typename T > struct get_capability_list { using type= Nil; }; - - template< CapabilityList T > - struct get_capability_list< T > - { - using type= decltype( extract_list( std::declval< const T & >() ) ); + static constexpr bool value= false + or DerivedFrom< car_t< List >, Capability > + or list_matches_v< cdr_t< List >, Capability > + ; }; + - template - < - template< typename ... > class Built, - typename ... LeftArgs, - typename ... RightArgs, - CapabilityList List - > - struct get_capability_list< Built< LeftArgs..., List, RightArgs... > > + template< typename Capability, typename List > + concept CapabilityInList= list_matches_v< List, Capability >; + + Nil get_capability_list( ... ); + + template< typename ... List > + struct exports::Capabilities { - using type= typename get_capability_list< List >::type; + friend constexpr TypeList< List... > + get_capability_list( const auto & ); }; - template< typename T > - using get_capability_list_t= typename get_capability_list< T >::type; - namespace exports { template< typename T, typename Capability > - constexpr bool has_capability_v= - has_capability_in_list_v< Capability, get_capability_list_t< T > > - or - DerivedFrom< T, Capability >; - - template< typename T, typename Capability > - concept HasCapability= has_capability_v< T, 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 >; } struct capability_demo {}; @@ -92,16 +70,6 @@ namespace Alepha::Hydrogen template< typename= Capabilities< capability_demo > > struct Example_base {}; using Example= Example_base<>; - static_assert( not DerivedFrom< Example, capability_demo > ); - static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > ); - using XXx= get_capability_list_t< Capabilities< capability_demo > >; - constexpr XXx qqq= TypeList< capability_demo >{}; - constexpr TypeList< capability_demo > zzz= get_capability_list_t< Example >{}; - static_assert( std::is_same_v< get_capability_list_t< Capabilities< capability_demo > >, TypeList< capability_demo > > ); - static_assert( std::is_same_v< get_capability_list_t< Example >, TypeList< capability_demo > > ); - static_assert( std::is_same_v< capability_demo, car_t< get_capability_list_t< Example > > > == true ); - static_assert( has_capability_in_list_v< capability_demo, TypeList< capability_demo > > == true ); - static_assert( has_capability_in_list_v< capability_demo, get_capability_list_t< Example > > == true ); static_assert( HasCapability< Example, capability_demo > == true ); static_assert( HasCapability< Example, missing_capability_demo > == false ); template< HasCapability< missing_capability_demo > C > void f( C ) {} diff --git a/comparisons.h b/comparisons.h index ab0ebfa..0b054be 100644 --- a/comparisons.h +++ b/comparisons.h @@ -28,16 +28,10 @@ namespace Alepha::Hydrogen namespace exports { using detail::comparisons_m::comparable; - inline constexpr Meta::type_value< comparable > comparable_capability; } template< typename T > - constexpr bool has_comparable_capability_v= has_capability( Meta::type_value< std::decay_t< T > >{}, comparable_capability ); - - 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; + constexpr bool has_comparable_capability_v= HasCapability< std::decay_t< T >, comparable >; // Spaceship lens support @@ -54,7 +48,7 @@ namespace Alepha::Hydrogen template < 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 > >, overload< __LINE__ > = nullptr > diff --git a/comparisons.test/0.cc b/comparisons.test/0.cc index baa0ab8..0603a3a 100644 --- a/comparisons.test/0.cc +++ b/comparisons.test/0.cc @@ -6,6 +6,9 @@ static_assert( __cplusplus > 2020'99 ); #include #include +#include +#include + namespace { using Alepha::Hydrogen::exports::types_m::argcnt_t; @@ -19,8 +22,8 @@ namespace < typename= int, typename= Capabilities< comparable >, - typename= float, - typename= Capabilities< short > + typename= float//, + //typename= Capabilities< short > > struct Date_core { @@ -43,8 +46,8 @@ namespace 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( detail::is_capability_list_v< Capabilities< comparable > > ); - static_assert( Alepha::has_capability( Meta::type_value< Date >{}, comparable_capability ) ); + //static_assert( detail::is_capability_list_v< Capabilities< comparable > > ); + static_assert( Alepha::HasCapability< Date, Alepha::comparable > ); template< template< typename > class op, typename T > constexpr bool diff --git a/swappable.h b/swappable.h index 3e0bb22..9271de1 100644 --- a/swappable.h +++ b/swappable.h @@ -96,7 +96,7 @@ namespace Alepha::Hydrogen ::detail:: swappable_m }; 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 diff --git a/type_lisp.h b/type_lisp.h index 115b075..23e1a62 100644 --- a/type_lisp.h +++ b/type_lisp.h @@ -5,6 +5,7 @@ static_assert( __cplusplus > 2020'99 ); #include #include +#include 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; } + 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 { template< typename List, typename Element > - constexpr bool list_contains_v= - 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 >{}; + constexpr bool list_contains_v= list_contains< List, Element >::value; } + 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 > struct cons; From 9224e986168e15cbad77a7a5dbc82c3768458eeb Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sat, 27 Jan 2024 05:12:07 -0500 Subject: [PATCH 3/4] Type List concatenation for type-lisp. --- type_lisp.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/type_lisp.h b/type_lisp.h index 23e1a62..ca2331f 100644 --- a/type_lisp.h +++ b/type_lisp.h @@ -126,6 +126,21 @@ namespace Alepha::Hydrogen ::detail:: type_lisp_m { using type= TypeList< Members... >; }; + + template< typename Left, typename Right > + struct list_cat; + + namespace exports + { + template< typename Left, typename Right > + using list_cat_t= typename list_cat< Left, Right >::type; + } + + template< typename ... LeftArgs, typename ... RightArgs > + struct list_cat< TypeList< LeftArgs... >, TypeList< RightArgs... > > + { + using type= TypeList< LeftArgs..., RightArgs... >; + }; } namespace Alepha::Hydrogen::inline exports::inline type_lisp_m From 60ed507e8dda16345fbce068d1e6cc5b0fa9b3fe Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Sat, 27 Jan 2024 05:12:43 -0500 Subject: [PATCH 4/4] Capabilities clauses can now be repeated. --- CMakeLists.txt | 1 + Capabilities.h | 49 +++++++++++++++++++++++++------- Capabilities.test/0.cc | 27 ++++++++++++++++++ Capabilities.test/CMakeLists.txt | 1 + comparisons.test/0.cc | 9 ++++-- 5 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 Capabilities.test/0.cc create mode 100644 Capabilities.test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index b206fd2..77b9477 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ add_subdirectory( Thread.test ) add_subdirectory( assertion.test ) add_subdirectory( Constness.test ) add_subdirectory( Blob.test ) +add_subdirectory( Capabilities.test ) # Sample applications add_executable( example example.cc ) diff --git a/Capabilities.h b/Capabilities.h index c9ce223..d3e73d1 100644 --- a/Capabilities.h +++ b/Capabilities.h @@ -36,7 +36,7 @@ namespace Alepha::Hydrogen or list_matches_v< cdr_t< List >, Capability > ; }; - + template< typename Capability, typename List > concept CapabilityInList= list_matches_v< List, Capability >; @@ -50,6 +50,44 @@ namespace Alepha::Hydrogen 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 > @@ -64,15 +102,6 @@ namespace Alepha::Hydrogen template< typename T, typename Cap > concept Capability= HasCapability< T, Cap >; } - - 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 ) {} } namespace exports::Capabilities_m diff --git a/Capabilities.test/0.cc b/Capabilities.test/0.cc new file mode 100644 index 0000000..ddc1c2e --- /dev/null +++ b/Capabilities.test/0.cc @@ -0,0 +1,27 @@ +static_assert( __cplusplus > 2020'99 ); + +#include "../Capabilities.h" + +#include +#include + + +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 <=[] +{ +}; diff --git a/Capabilities.test/CMakeLists.txt b/Capabilities.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Capabilities.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 ) diff --git a/comparisons.test/0.cc b/comparisons.test/0.cc index 0603a3a..7f3c60f 100644 --- a/comparisons.test/0.cc +++ b/comparisons.test/0.cc @@ -18,12 +18,14 @@ namespace using namespace Alepha::Hydrogen::exports::comparisons_m; using namespace Alepha::Hydrogen::exports::Capabilities_m; + struct blast {}; + template < typename= int, - typename= Capabilities< comparable >, - typename= float//, - //typename= Capabilities< short > + typename= Capabilities< blast >, + typename= float, + typename= Capabilities< comparable > > struct Date_core { @@ -48,6 +50,7 @@ namespace //static_assert( detail::is_capability_list_v< Capabilities< comparable > > ); static_assert( Alepha::HasCapability< Date, Alepha::comparable > ); + static_assert( Alepha::HasCapability< Date, blast > ); template< template< typename > class op, typename T > constexpr bool