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:
@ -15,6 +15,29 @@ namespace Alepha::Hydrogen::Meta::Container
|
||||
inline namespace exports
|
||||
{
|
||||
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 >
|
||||
@ -44,6 +67,22 @@ namespace Alepha::Hydrogen::Meta::Container
|
||||
{
|
||||
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 >
|
||||
constexpr bool
|
||||
|
||||
40
Meta/find.h
40
Meta/find.h
@ -4,7 +4,7 @@ static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||
|
||||
#include <Alepha/Alepha.h>
|
||||
|
||||
#include <tuple>
|
||||
#include <functional>
|
||||
|
||||
#include <Alepha/Meta/Container/vector.h>
|
||||
#include <Alepha/Meta/functional.h>
|
||||
@ -17,29 +17,23 @@ namespace Alepha::Hydrogen::Meta
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
template< typename Predicate, typename Tuple >
|
||||
struct find_if;
|
||||
template< typename Iter, typename Predicate >
|
||||
constexpr bool
|
||||
find_if( const Iter first, const Iter last, Predicate pred )
|
||||
{
|
||||
for( Iter pos= first; pos != last; ++pos )
|
||||
{
|
||||
if( pred( *pos ) ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template< typename Predicate, typename First, typename ... Elements >
|
||||
struct find_if< Predicate, Container::vector< First, Elements... > >
|
||||
: std::conditional_t
|
||||
<
|
||||
Meta::call< Predicate, First >::value,
|
||||
std::true_type,
|
||||
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 Key, typename Argument >
|
||||
constexpr bool find_v= find_if_v< Meta::bind1st< std::is_same, Key >, Argument >;
|
||||
template< typename Iter, typename Value >
|
||||
constexpr bool
|
||||
find( const Iter first, const Iter last, const Value value )
|
||||
{
|
||||
return find_if( first, last, Meta::bind1st( std::equal_to{}, value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,24 +14,38 @@ namespace Alepha::Hydrogen::Meta
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
template< template< typename, typename > class Function, typename First >
|
||||
struct bind1st
|
||||
{
|
||||
using type= bind1st;
|
||||
template< typename Arg >
|
||||
struct call : Function< First, Arg >::type {};
|
||||
};
|
||||
template< typename MetaFunction, typename Arg >
|
||||
constexpr auto bind1st( MetaFunction func, Arg arg );
|
||||
}
|
||||
|
||||
template< template< typename, typename > class Function, typename Second >
|
||||
struct bind2nd
|
||||
{
|
||||
using type= bind2nd;
|
||||
template< typename Arg >
|
||||
struct call : Function< Arg, Second >::type {};
|
||||
};
|
||||
template< typename MetaFunction, typename Arg > struct binder1st;
|
||||
|
||||
template< typename Function, typename ... Args >
|
||||
struct call : Function::template call< Args... > {};
|
||||
template< typename MetaFunction, typename Arg1, typename Arg2 >
|
||||
constexpr decltype( auto )
|
||||
invoke_call( MetaFunction func, Meta::type_value< Arg1 > arg1, Meta::type_value< Arg2 > arg2 )
|
||||
{
|
||||
return func( arg1, arg2 );
|
||||
}
|
||||
|
||||
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< typename MetaFunction, typename Arg >
|
||||
constexpr auto
|
||||
exports::bind1st( MetaFunction func, Arg arg )
|
||||
{
|
||||
return binder1st< MetaFunction, Arg >{ func, arg };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
24
Meta/test.cc
24
Meta/test.cc
@ -1,8 +1,9 @@
|
||||
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||
|
||||
#include <Alepha/Meta/is_sequence.h>
|
||||
|
||||
#include <Alepha/Meta/is_streamable.h>
|
||||
#include <Alepha/Meta/type_value.h>
|
||||
#include <Alepha/Meta/Container/vector.h>
|
||||
|
||||
#include <Alepha/Testing/test.h>
|
||||
|
||||
@ -21,6 +22,8 @@ namespace
|
||||
using namespace Alepha::Utility::evaluation;
|
||||
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
|
||||
// as unit tests. There's no call to actually assert them at runtime. If this test built,
|
||||
// it passes.
|
||||
@ -115,6 +118,25 @@ namespace
|
||||
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 >{} ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -12,21 +12,35 @@ namespace Alepha::Hydrogen::Meta
|
||||
{
|
||||
inline namespace exports
|
||||
{
|
||||
template< typename >
|
||||
struct type_value {};
|
||||
template< typename Type >
|
||||
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 >
|
||||
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
|
||||
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 >
|
||||
@ -35,6 +49,34 @@ namespace Alepha::Hydrogen::Meta
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user