From 4538a8d943e8546017e1d4ce3ca2f9ec9c94e5bf Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Mon, 25 Oct 2021 01:58:04 -0400 Subject: [PATCH] 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. --- Meta/Container/vector.h | 123 ++++++++++++++++++++++++++++++++++++++++ Meta/find.h | 45 +++++++++++++++ Meta/functional.h | 42 ++++++++++++++ Meta/type_value.h | 45 +++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 Meta/Container/vector.h create mode 100644 Meta/find.h create mode 100644 Meta/functional.h create mode 100644 Meta/type_value.h diff --git a/Meta/Container/vector.h b/Meta/Container/vector.h new file mode 100644 index 0000000..1832dfa --- /dev/null +++ b/Meta/Container/vector.h @@ -0,0 +1,123 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +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; + } +} diff --git a/Meta/find.h b/Meta/find.h new file mode 100644 index 0000000..e9e9fa3 --- /dev/null +++ b/Meta/find.h @@ -0,0 +1,45 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +#include +#include + +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; + } +} diff --git a/Meta/functional.h b/Meta/functional.h new file mode 100644 index 0000000..f84aaf3 --- /dev/null +++ b/Meta/functional.h @@ -0,0 +1,42 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +// Analogue to `#include ` + +#include + +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; + } +} diff --git a/Meta/type_value.h b/Meta/type_value.h new file mode 100644 index 0000000..b9679d2 --- /dev/null +++ b/Meta/type_value.h @@ -0,0 +1,45 @@ +static_assert( __cplusplus > 2017, "C++17 Required" ); + +#pragma once + +#include + +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; + } +}