forked from Alepha/Alepha
A few metaprogramming tools.
This commit is contained in:
93
Meta/Container/string.h
Normal file
93
Meta/Container/string.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include <Alepha/comparisons.h>
|
||||||
|
#include <Alepha/Constexpr/algorithm.h>
|
||||||
|
#include <Alepha/Constexpr/array.h>
|
||||||
|
|
||||||
|
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... >{} };
|
||||||
|
}
|
||||||
|
};
|
||||||
223
Meta/type_algorithm.h
Normal file
223
Meta/type_algorithm.h
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
static_assert( __cplusplus > 201700, "C++17 Required" );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include <Alepha/Constexpr/algorithm.h>
|
||||||
|
#include <Alepha/Constexpr/array.h>
|
||||||
|
|
||||||
|
#include <Alepha/Meta/Container/vector.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user