forked from Alepha/Alepha
Add a bunch of TMP support.
I'm still on the fence about going full `constexpr` functions for meta-code. Overall, I think there's potential here. I'm not aiming to replicate what `boost::mpl` or `boost::hana` do though. This is more of an internal support mechanism for Alepha code. As-needed I'll implement things.
This commit is contained in:
123
Meta/Container/vector.h
Normal file
123
Meta/Container/vector.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <Alepha/Meta/type_value.h>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::Meta::Container
|
||||||
|
{
|
||||||
|
inline namespace exports { inline namespace meta_container_vector {} }
|
||||||
|
|
||||||
|
namespace detail::meta_container_vector
|
||||||
|
{
|
||||||
|
inline namespace exports
|
||||||
|
{
|
||||||
|
template< typename ... Members > struct vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Vector >
|
||||||
|
struct vector_iterator
|
||||||
|
{
|
||||||
|
int offset= 0;
|
||||||
|
|
||||||
|
constexpr auto operator *() const;
|
||||||
|
constexpr vector_iterator &operator ++() { ++offset; return *this; }
|
||||||
|
constexpr vector_iterator operator++ ( int ) { auto rv= *this; ++offset; return rv; }
|
||||||
|
|
||||||
|
friend constexpr bool
|
||||||
|
operator == ( const vector_iterator &lhs, const vector_iterator &rhs )
|
||||||
|
{
|
||||||
|
return lhs.offset == rhs.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool
|
||||||
|
operator != ( const vector_iterator &lhs, const vector_iterator &rhs )
|
||||||
|
{
|
||||||
|
return lhs.offset != rhs.offset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename List >
|
||||||
|
struct dereferenced_iterator
|
||||||
|
{
|
||||||
|
vector_iterator< List > iter;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename First, typename ... Members, typename Value >
|
||||||
|
constexpr bool
|
||||||
|
operator == ( const dereferenced_iterator< vector< First, Members... > > deref, type_value< Value > value )
|
||||||
|
{
|
||||||
|
if( deref.iter.offset == 0 ) return type_value< First >{} == value;
|
||||||
|
else return dereferenced_iterator< vector< Members... > >{ deref.iter.offset - 1 } == value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Value >
|
||||||
|
constexpr bool
|
||||||
|
operator == ( const dereferenced_iterator< vector<> > iter, type_value< Value > value )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Vector >
|
||||||
|
constexpr auto
|
||||||
|
vector_iterator< Vector >::operator *() const
|
||||||
|
{
|
||||||
|
return dereferenced_iterator< Vector >{ *this };
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename ... Members >
|
||||||
|
struct exports::vector
|
||||||
|
{
|
||||||
|
using iterator= vector_iterator< vector >;
|
||||||
|
using const_iterator= vector_iterator< vector >;
|
||||||
|
|
||||||
|
constexpr auto begin() const { return vector_iterator< vector >{}; }
|
||||||
|
constexpr auto end() const { return vector_iterator< vector >{ sizeof...( Members ) }; }
|
||||||
|
|
||||||
|
template< typename Type >
|
||||||
|
[[nodiscard]] constexpr auto
|
||||||
|
push_back( type_value< Type > ) const
|
||||||
|
{
|
||||||
|
return vector< Members..., Type >{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Type >
|
||||||
|
[[nodiscard]] constexpr auto
|
||||||
|
push_front( type_value< Type > ) const
|
||||||
|
{
|
||||||
|
return vector< Type, Members... >{};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto
|
||||||
|
clear() const
|
||||||
|
{
|
||||||
|
return vector<>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool empty() const { return size() == 0; }
|
||||||
|
constexpr bool size() const { return sizeof...( Members ); }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename ... LhsMembers, typename ... RhsMembers >
|
||||||
|
constexpr bool
|
||||||
|
operator == ( const vector< LhsMembers... > &lhs, const vector< RhsMembers... > &rhs )
|
||||||
|
{
|
||||||
|
return make_value_type( lhs ) == make_value_type( rhs );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename ... LhsMembers, typename ... RhsMembers >
|
||||||
|
constexpr bool
|
||||||
|
operator != ( const vector< LhsMembers... > &lhs, const vector< RhsMembers... > &rhs )
|
||||||
|
{
|
||||||
|
return make_value_type( lhs ) != make_value_type( rhs );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace exports::meta_container_vector
|
||||||
|
{
|
||||||
|
using namespace detail::meta_container_vector::exports;
|
||||||
|
}
|
||||||
|
}
|
45
Meta/find.h
Normal file
45
Meta/find.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include <Alepha/Meta/list.h>
|
||||||
|
#include <Alepha/Meta/functional.h>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::Meta
|
||||||
|
{
|
||||||
|
inline namespace exports { inline namespace find_algos {} }
|
||||||
|
|
||||||
|
namespace detail::find_algos
|
||||||
|
{
|
||||||
|
inline namespace exports
|
||||||
|
{
|
||||||
|
template< typename Predicate, typename Tuple >
|
||||||
|
struct find_if;
|
||||||
|
|
||||||
|
template< typename Predicate, typename First, typename ... Elements >
|
||||||
|
struct find_if< Predicate, list< First, Elements... > >
|
||||||
|
: std::conditional_t< Meta::call< Predicate, First >::value, std::true_type, find_if< Predicate, list< Elements... > > >::type {};
|
||||||
|
|
||||||
|
template< typename Predicate >
|
||||||
|
struct find_if< Predicate, list<> > : 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 >;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace exports::find_algos
|
||||||
|
{
|
||||||
|
using namespace detail::find_algos::exports;
|
||||||
|
}
|
||||||
|
}
|
42
Meta/functional.h
Normal file
42
Meta/functional.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Analogue to `#include <functional>`
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::Meta
|
||||||
|
{
|
||||||
|
inline namespace exports { inline namespace functional {} }
|
||||||
|
|
||||||
|
namespace detail::functional
|
||||||
|
{
|
||||||
|
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< template< typename, typename > class Function, typename Second >
|
||||||
|
struct bind2nd
|
||||||
|
{
|
||||||
|
using type= bind2nd;
|
||||||
|
template< typename Arg >
|
||||||
|
struct call : Function< Arg, second >::type {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename Function, typename ... Args >
|
||||||
|
struct call : Function::template call< Args... > {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace exports::functional
|
||||||
|
{
|
||||||
|
using namespace detail::functional::exports;
|
||||||
|
}
|
||||||
|
}
|
45
Meta/type_value.h
Normal file
45
Meta/type_value.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
static_assert( __cplusplus > 2017, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::Meta
|
||||||
|
{
|
||||||
|
inline namespace exports { inline namespace type_value_wrapper {} }
|
||||||
|
|
||||||
|
namespace detail::type_value_wrapper
|
||||||
|
{
|
||||||
|
inline namespace exports
|
||||||
|
{
|
||||||
|
template< typename >
|
||||||
|
struct type_value {};
|
||||||
|
|
||||||
|
template< typename Lhs, typename Rhs >
|
||||||
|
constexpr bool
|
||||||
|
operator == ( type_value< Lhs >, type_value< Rhs > )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename Value >
|
||||||
|
constexpr bool
|
||||||
|
operator == ( type_value< Value >, type_value< Value > )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
constexpr auto
|
||||||
|
make_value_type( T&& )
|
||||||
|
{
|
||||||
|
return type_value< std::decay_t< T > >{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace exports::type_value_wrapper
|
||||||
|
{
|
||||||
|
using namespace detail::type_value_wrapper::exports;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user