diff --git a/Meta/Container/string.h b/Meta/Container/string.h new file mode 100644 index 0000000..f22127d --- /dev/null +++ b/Meta/Container/string.h @@ -0,0 +1,93 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +#include +#include +#include + +namespace Alepha::Hydrogen::Meta::Container +{ + inline namespace exports { inline namespace meta_container_string {} } + + namespace detail::meta_container_string + { + inline namespace exports {} + + namespace C + { + const std::size_t amount= 4096; + } + + namespace exports + { + template< typename CharT > class basic_string; + + template< typename CharT, CharT ... text > + struct constexpr_str_wrapper + : comparable + { + #define MAKE_OP( op ) \ + template< CharT ... text2 > \ + constexpr friend bool \ + operator op ( const constexpr_str_wrapper< CharT, text... > lhs, const constexpr_str_wrapper< CharT, text2... > rhs ) \ + { \ + return basic_string< CharT >{ lhs } op basic_string< CharT >{ rhs }; \ + } + + MAKE_OP( < ); + MAKE_OP( > ); + + MAKE_OP( <= ); + MAKE_OP( >= ); + + MAKE_OP( == ); + MAKE_OP( != ); + + #undef MAKE_OP + }; + + template< typename CharT > + class basic_string + : public comparable + { + private: + Constexpr::array< CharT, C::amount > raw; + + public: + template< CharT ... text > + constexpr explicit + basic_string( constexpr_str_wrapper< CharT, text... > ) + : raw() + { + CharT chars[]= { text..., '\0' }; + using std::begin, std::end; + Constexpr::copy( begin( chars ), end( chars ), begin( raw ) ); + } + + constexpr auto value_lens() const noexcept { return ordering_magma( raw ); } + }; + + using string= basic_string< char >; + } + } + + namespace exports::meta_container_string + { + using namespace detail::meta_container_string::exports; + } +} + +template< typename CharT, CharT ... text > +struct Alepha::Meta::unique_for_type_binder< Alepha::Meta::type_value< Alepha::Meta::Container::constexpr_str_wrapper< CharT, text... > > > +{ + static constexpr auto + build() noexcept + { + return Alepha::Meta::Container::basic_string{ Alepha::Meta::Container::constexpr_str_wrapper< CharT, text... >{} }; + } +}; diff --git a/Meta/type_algorithm.h b/Meta/type_algorithm.h new file mode 100644 index 0000000..823bd6a --- /dev/null +++ b/Meta/type_algorithm.h @@ -0,0 +1,223 @@ +static_assert( __cplusplus > 201700, "C++17 Required" ); + +#pragma once + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +namespace Alepha::Hydrogen::Meta +{ + inline namespace exports { inline namespace type_algorithm {} } + + namespace detail::type_algorithm + { + inline namespace exports + { + template< typename T > struct unique_for_type_binder; + + template< typename T > constexpr auto unique_for_type= unique_for_type_binder< T >::build(); + } + + using Container::vector; + + template< typename, typename > struct type_less; + + //template< typename A > + //struct type_less< A, A > : std::false_type {}; + + constexpr bool + char_string_less( const char *left, const char *right ) + { + // std::cerr << "Comparing..." << std::endl; + // std::cerr << left << std::endl; + // std::cerr << right << std::endl; + while( *left and *right ) + { + // std::cerr << "Comparing \"" << *left << "\" to \"" << *right << '"' << std::endl; + if( *left < *right ) return true; + if( *left > *right ) return false; + assert( *left == *right ); + ++left; ++right; + } + // std::cerr << "Ran out of chars..." << std::endl; + if( *left == *right ) return false; + if( *left ) return false; + return true; + } + + constexpr bool + char_string_eq( const char *left, const char *right ) + { + while( *left and *right ) + { + if( *left++ != *right++ ) return false; + } + return *left == *right; + } + + template< typename T > + constexpr const char * + single_type_value() + { + return __PRETTY_FUNCTION__; + } + + template< typename A, typename B > + constexpr bool + compute() + { + return char_string_less( single_type_value< A >(), single_type_value< B >() ); + } + + template< typename A, typename B > + struct type_less + { + static const bool value= compute< A, B >(); + }; + + template< typename A, typename B > + constexpr bool type_less_v= type_less< A, B >::value; + + template< typename T > + constexpr void + constexpr_swap( T &a, T &b ) noexcept + { + T tmp= std::move( a ); + a= std::move( b ); + b= std::move( tmp ); + } + + template< typename Iter, typename Comp > + constexpr void + constexpr_sort( Iter first, Iter last, Comp comp ) + { + if( first == last ) return; + const auto pos= std::min_element( first, last, comp ); + using std::swap; + constexpr_swap( *pos, *first ); + constexpr_sort( ++first, last, comp ); + } + + namespace exports + { + template< typename ... Types > + constexpr bool + all_unique() noexcept + { + std::array< const char *, sizeof...( Types ) > magic_values= { single_type_value< Types >()... }; + using std::begin, std::end; + + const std::size_t amt= magic_values.size(); + if constexpr( amt <= 1 ) return true; + else + { + constexpr_sort( begin( magic_values ), end( magic_values ), &char_string_less ); + for( auto pos= begin( magic_values ); pos < end( magic_values ) - 1; ++pos ) + { + if( char_string_eq( *pos, *( pos + 1 ) ) ) return false; + } + return true; + } + } + } + + template< typename ... Types > + struct lowest_type_impl; + + template< typename Type > + struct lowest_type_impl< Type > + { + using type= Type; + }; + + template< typename Type, typename ... Types > + struct lowest_type_impl< Type, Types... > + { + using later_lowest= typename lowest_type_impl< Types... >::type; + + using type= std::conditional_t + < + type_less_v< Type, later_lowest >, + Type, + later_lowest + >; + }; + + namespace exports + { + template< typename ... Types > + using lowest_type_t= typename lowest_type_impl< Types... >::type; + } + + template< typename Left, typename Right > + struct concat_vectors; + + template< typename ... Left, typename ... Right > + struct concat_vectors< vector< Left... >, vector< Right... > > + { + using type= vector< Left..., Right... >; + }; + + template< typename Left, typename Right > + using concat_vectors_t= typename concat_vectors< Left, Right >::type; + + template< typename Type, typename Group > + struct remove_type_impl; + + template< typename Type, typename ... Types > + struct remove_type_impl< Type, vector< Type, Types... > > + { + using type= vector< Types... >; + }; + + template< typename Type, typename First, typename ... Types > + struct remove_type_impl< Type, vector< First, Types... > > + { + using type= concat_vectors_t< vector< First >, typename remove_type_impl< Type, vector< Types... > >::type >; + }; + + template< typename Type, typename Vector > + using remove_type_t= typename remove_type_impl< Type, Vector >::type; + + template< typename Type > + struct type_sort_vector; + + template< typename Type > + struct type_sort_vector< vector< Type > > + { + using type= vector< Type >; + }; + + template< typename ... Types > + struct type_sort_vector< vector< Types... > > + { + using lowest= lowest_type_t< Types... >; + using type= concat_vectors_t< vector< lowest >, remove_type_t< lowest, vector< Types... > > >; + }; + + namespace exports + { + template< typename ... Types > + using type_sort_t= typename type_sort_vector< vector< Types... > >::type; + + using detail::type_algorithm::type_less_v; + using detail::type_algorithm::single_type_value; + using detail::type_algorithm::char_string_less; + } + } + + namespace exports::type_algorithm + { + using namespace detail::type_algorithm::exports; + } +}