1
0
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:
2021-10-26 01:53:47 -04:00
parent e3d7bbe616
commit cf3f77ba6e
8 changed files with 221 additions and 80 deletions

View File

@ -5,7 +5,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
#include <Alepha/Alepha.h> #include <Alepha/Alepha.h>
#include <Alepha/Meta/find.h> #include <Alepha/Meta/find.h>
#include <Alepha/Stud/type_traits.h> #include <Alepha/Meta/type_value.h>
namespace Alepha::Hydrogen namespace Alepha::Hydrogen
{ {
@ -19,7 +19,7 @@ namespace Alepha::Hydrogen
struct Capabilities; struct Capabilities;
template< typename T, typename cap > 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 #if 0
@ -50,58 +50,68 @@ namespace Alepha::Hydrogen
} }
template< typename T > template< typename T >
struct is_capability_list : std::false_type {}; struct is_capability_list_s : std::false_type {};
template< typename ... Args > 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 > 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 > template< template< typename ... > class ... HigherKinds >
struct higher_kind_tuple {}; struct higher_kind_tuple {};
template< typename cap, typename ... Caps > template< typename Cap, typename ... Caps >
constexpr auto constexpr bool
has_cap( const Stud::type_identity< Capabilities< Caps... > > & ) 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 > template< typename Left, typename Cap >
constexpr std::false_type has_cap( const Meta::Container::vector<> & ) { return {}; } constexpr bool
has_cap_in_capability_base( const Left &, Meta::type_value< Cap > cap )
template< typename cap, typename First, typename ... TParams >
constexpr auto
has_cap( const Meta::Container::vector< First, TParams... > & )
{ {
using depth_type= decltype( has_cap< cap >( Meta::Container::vector< TParams... >{} ) ); throw "Unevaluated";
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 > template< typename Cap, typename ... TParams >
constexpr auto constexpr bool
has_cap( const Class< TParams... > & ) has_cap( const Meta::Container::vector< TParams... > &types, Meta::type_value< Cap > cap )
{ {
return has_cap< cap >( Meta::Container::vector< TParams... >{} ); 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 >
constexpr bool
has_cap( const Meta::type_value< Class< TParams... > > &, Meta::type_value< Cap > cap )
{
return has_cap( Meta::Container::vector< TParams... >{}, cap );
} }
namespace exports namespace exports
{ {
template< typename T, typename cap > 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 > 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;
} }
} }

View File

@ -15,6 +15,29 @@ namespace Alepha::Hydrogen::Meta::Container
inline namespace exports inline namespace exports
{ {
template< typename ... Members > struct vector; template< typename ... Members > struct vector;
template< typename ... Members >
constexpr auto
template_for( vector< Members... > );
}
template< typename ... Members >
struct template_for_binder
{
template< typename Body >
constexpr void
operator <=( Body b )
{
auto wrapper= [&]( auto element ) { b( element ); return nullptr; };
std::nullptr_t loop[]= { wrapper( type_value< Members >{} )... };
}
};
template< typename ... Members >
constexpr auto
exports::template_for( vector< Members... > )
{
return template_for_binder< Members... >{};
} }
template< typename Vector > template< typename Vector >
@ -45,6 +68,22 @@ namespace Alepha::Hydrogen::Meta::Container
vector_iterator< List > iter; vector_iterator< List > iter;
}; };
template< typename MetaFunction, typename Arg1, typename First, typename ... Members >
constexpr decltype( auto )
invoke_call( MetaFunction func, type_value< Arg1 > arg1, dereferenced_iterator< vector< First, Members... > > deref )
{
if( deref.iter.offset == 0 ) return func( arg1, type_value< First >{} );
else return invoke_call( func, arg1, dereferenced_iterator< vector< Members... > >{ deref.iter.offset - 1 } );
}
template< typename MetaFunction, typename Arg1, typename First >
constexpr decltype( auto )
invoke_call( MetaFunction func, type_value< Arg1 > arg1, dereferenced_iterator< vector< First > > deref )
{
if( deref.iter.offset == 0 ) return func( arg1, type_value< First >{} );
else throw "Out of bounds iterator";
}
template< typename First, typename ... Members, typename Value > template< typename First, typename ... Members, typename Value >
constexpr bool constexpr bool
operator == ( const dereferenced_iterator< vector< First, Members... > > deref, type_value< Value > value ) operator == ( const dereferenced_iterator< vector< First, Members... > > deref, type_value< Value > value )

View File

@ -4,7 +4,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
#include <Alepha/Alepha.h> #include <Alepha/Alepha.h>
#include <tuple> #include <functional>
#include <Alepha/Meta/Container/vector.h> #include <Alepha/Meta/Container/vector.h>
#include <Alepha/Meta/functional.h> #include <Alepha/Meta/functional.h>
@ -17,29 +17,23 @@ namespace Alepha::Hydrogen::Meta
{ {
inline namespace exports inline namespace exports
{ {
template< typename Predicate, typename Tuple > template< typename Iter, typename Predicate >
struct find_if; constexpr bool
find_if( const Iter first, const Iter last, Predicate pred )
template< typename Predicate, typename First, typename ... Elements > {
struct find_if< Predicate, Container::vector< First, Elements... > > for( Iter pos= first; pos != last; ++pos )
: std::conditional_t {
< if( pred( *pos ) ) return true;
Meta::call< Predicate, First >::value, }
std::true_type, return false;
find_if< Predicate, Container::vector< Elements... > >
>::type {};
template< typename Predicate >
struct find_if< Predicate, Container::vector<> > : std::false_type {};
template< typename Predicate, typename List >
constexpr bool find_if_v= find_if< Predicate, List >::value;
} }
namespace exports template< typename Iter, typename Value >
constexpr bool
find( const Iter first, const Iter last, const Value value )
{ {
template< typename Key, typename Argument > return find_if( first, last, Meta::bind1st( std::equal_to{}, value ) );
constexpr bool find_v= find_if_v< Meta::bind1st< std::is_same, Key >, Argument >; }
} }
} }

View File

@ -14,24 +14,38 @@ namespace Alepha::Hydrogen::Meta
{ {
inline namespace exports inline namespace exports
{ {
template< template< typename, typename > class Function, typename First > template< typename MetaFunction, typename Arg >
struct bind1st constexpr auto bind1st( MetaFunction func, Arg arg );
}
template< typename MetaFunction, typename Arg > struct binder1st;
template< typename MetaFunction, typename Arg1, typename Arg2 >
constexpr decltype( auto )
invoke_call( MetaFunction func, Meta::type_value< Arg1 > arg1, Meta::type_value< Arg2 > arg2 )
{ {
using type= bind1st; return func( arg1, arg2 );
template< typename Arg > }
struct call : Function< First, Arg >::type {};
template< typename MetaFunction, typename Arg >
struct binder1st< MetaFunction, Meta::type_value< Arg > >
{
MetaFunction func;
Meta::type_value< Arg > arg;
template< typename Second >
constexpr decltype( auto )
operator () ( const Second &second )
{
return invoke_call( func, arg, second );
}
}; };
template< template< typename, typename > class Function, typename Second > template< typename MetaFunction, typename Arg >
struct bind2nd constexpr auto
exports::bind1st( MetaFunction func, Arg arg )
{ {
using type= bind2nd; return binder1st< MetaFunction, Arg >{ func, arg };
template< typename Arg >
struct call : Function< Arg, Second >::type {};
};
template< typename Function, typename ... Args >
struct call : Function::template call< Args... > {};
} }
} }

View File

@ -1,8 +1,9 @@
static_assert( __cplusplus > 201700, "C++17 Required" ); static_assert( __cplusplus > 201700, "C++17 Required" );
#include <Alepha/Meta/is_sequence.h> #include <Alepha/Meta/is_sequence.h>
#include <Alepha/Meta/is_streamable.h> #include <Alepha/Meta/is_streamable.h>
#include <Alepha/Meta/type_value.h>
#include <Alepha/Meta/Container/vector.h>
#include <Alepha/Testing/test.h> #include <Alepha/Testing/test.h>
@ -21,6 +22,8 @@ namespace
using namespace Alepha::Utility::evaluation; using namespace Alepha::Utility::evaluation;
using namespace Alepha::Testing::literals; using namespace Alepha::Testing::literals;
using std::begin, std::end;
// These tests never actually fail at runtime, but they provide a simple way to have them // These tests never actually fail at runtime, but they provide a simple way to have them
// as unit tests. There's no call to actually assert them at runtime. If this test built, // as unit tests. There's no call to actually assert them at runtime. If this test built,
// it passes. // it passes.
@ -115,6 +118,25 @@ namespace
static_assert( not Alepha::Meta::is_streamable_v< void > ); static_assert( not Alepha::Meta::is_streamable_v< void > );
}; };
}; };
namespace MetaContainer= Alepha::Meta::Container::exports;
using Alepha::Meta::type_value;
constexpr MetaContainer::vector< int, float, char > my_list;
template< typename First, typename Last, typename Type >
constexpr bool
containsChar( First first, Last last, type_value< Type > value )
{
for( auto pos= first; pos != last; ++pos )
{
if( *pos == value ) return true;
}
return false;
}
static_assert( containsChar( begin( my_list ), end( my_list ), type_value< char >{} ) );
static_assert( not containsChar( begin( my_list ), end( my_list ), type_value< long double >{} ) );
static_assert( containsChar( begin( my_list ), end( my_list ), type_value< int >{} ) );
} }

View File

@ -12,21 +12,35 @@ namespace Alepha::Hydrogen::Meta
{ {
inline namespace exports inline namespace exports
{ {
template< typename > template< typename Type >
struct type_value {}; struct type_value { using type= Type; };
template< template< typename > class Trait, typename Value >
constexpr bool
check_trait( type_value< Value > )
{
return Trait< Value >::value;
}
template< template< typename, typename > class Trait, typename A, typename B >
constexpr bool
check_trait( type_value< A >, type_value< B > )
{
return Trait< A, B >::value;
}
template< typename Lhs, typename Rhs > template< typename Lhs, typename Rhs >
constexpr bool constexpr bool
operator == ( type_value< Lhs >, type_value< Rhs > ) operator == ( type_value< Lhs > lhs, type_value< Rhs > rhs )
{ {
return false; return check_trait< std::is_same >( lhs, rhs );
} }
template< typename Value > template< typename Lhs, typename Rhs >
constexpr bool constexpr bool
operator == ( type_value< Value >, type_value< Value > ) operator != ( type_value< Lhs > lhs, type_value< Rhs > rhs )
{ {
return true; return not( lhs == rhs );
} }
template< typename T > template< typename T >
@ -35,6 +49,34 @@ namespace Alepha::Hydrogen::Meta
{ {
return type_value< std::decay_t< T > >{}; return type_value< std::decay_t< T > >{};
} }
template< template< typename ... > class Trait > struct trait;
template< template< typename > class Trait >
struct trait< Trait >
{
template< typename Type >
constexpr bool
operator() ( type_value< Type > ) const
{
return Trait< Type >::value;
}
};
template< template< typename, typename > class Trait >
struct trait< Trait >
{
template< typename A, typename B >
constexpr bool
operator() ( type_value< A >, type_value< B > ) const
{
return Trait< A, B >::value;
}
};
inline constexpr trait< std::is_base_of > is_base_of;
inline constexpr trait< std::is_same > is_same;
inline constexpr trait< std::is_default_constructible > is_default_constructible;
} }
} }

View File

@ -25,9 +25,11 @@ namespace Alepha::Hydrogen
struct comparable {}; struct comparable {};
namespace exports namespace exports
{ {
using detail::comparisons::comparable; using detail::comparisons::comparable;
inline constexpr Meta::type_value< comparable > comparable_capability;
} }
template< typename T > template< typename T >

View File

@ -24,7 +24,13 @@ namespace
using namespace Alepha::exports::comparisons; using namespace Alepha::exports::comparisons;
using namespace Alepha::exports::capabilities; using namespace Alepha::exports::capabilities;
template< typename= int, typename= Capabilities< comparable >, typename= float, typename= Capabilities< short > > template
<
typename= int,
typename= Capabilities< comparable >,
typename= float,
typename= Capabilities< short >
>
struct Date_core struct Date_core
{ {
int y; int y;
@ -35,7 +41,19 @@ namespace
}; };
using Date= Date_core<>; using Date= Date_core<>;
static_assert( Alepha::has_capability_v< Date, comparable > ); namespace detail= Alepha::detail::capabilities;
namespace Meta= Alepha::Meta;
constexpr Meta::Container::vector< short, long, int, int, std::string, std::vector< int >, long, void, void > vec;
constexpr Meta::type_value< int > val;
using std::begin, std::end;
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 ) );
template< template< typename > class op, typename T > template< template< typename > class op, typename T >
constexpr bool constexpr bool