98 lines
2.8 KiB
Plaintext
98 lines
2.8 KiB
Plaintext
|
|
#pragma once
|
||
|
|
#include <type_traits>
|
||
|
|
#include "meta.h"
|
||
|
|
|
||
|
|
namespace meta
|
||
|
|
{
|
||
|
|
template<typename T, template<typename ...> typename TMPLT>
|
||
|
|
struct is_template
|
||
|
|
: std::false_type
|
||
|
|
{
|
||
|
|
};
|
||
|
|
|
||
|
|
template<template<typename ...> typename TMPLT, typename...Args>
|
||
|
|
struct is_template<TMPLT<Args...>, TMPLT>
|
||
|
|
: std::true_type
|
||
|
|
{
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
template<typename T, T ... Indexes1, T ... Indexes2>
|
||
|
|
struct index_sequence_cat<std::index_sequence<Indexes1...>, std::index_sequence<Indexes2...>>
|
||
|
|
{
|
||
|
|
using type = std::index_sequence<Indexes1..., Indexes2...>;
|
||
|
|
};
|
||
|
|
|
||
|
|
template<>
|
||
|
|
struct index_sequence_rev<std::index_sequence<>>
|
||
|
|
{
|
||
|
|
using type = std::index_sequence<>;
|
||
|
|
};
|
||
|
|
|
||
|
|
template<typename T, T Last, T ... Indexes>
|
||
|
|
struct index_sequence_rev<std::index_sequence<Indexes..., Last>>
|
||
|
|
{
|
||
|
|
using type = index_sequence_cat_t<std::index_sequence<Last>, index_sequence_rev_t<std::index_sequence<Indexes...>>>;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
template<typename T, typename = void>
|
||
|
|
struct is_iterable : std::false_type {};
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
struct is_iterable<T, std::void_t<decltype(
|
||
|
|
std::begin(std::declval<T&>()) != std::end(std::declval<T&>()), // begin/end and operator !=
|
||
|
|
void(), // Handle evil operator ,
|
||
|
|
++std::declval<decltype(std::begin(std::declval<T&>()))&>(), // operator ++
|
||
|
|
void(*std::begin(std::declval<T&>())) // operator*
|
||
|
|
)>> : std::true_type {};
|
||
|
|
|
||
|
|
template<typename T, typename = void>
|
||
|
|
struct is_sequential_container : std::is_array<std::decay_t<T>> {};
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
struct is_sequential_container<T, std::void_t<decltype(
|
||
|
|
std::declval<T&>().front()
|
||
|
|
)>> : is_iterable<T> {};
|
||
|
|
|
||
|
|
template<typename T, typename = void>
|
||
|
|
struct is_associative_container : std::false_type {};
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
struct is_associative_container<T, std::void_t<decltype(
|
||
|
|
std::declval<T&>().insert(std::declval<typename std::decay_t<T>::value_type>())
|
||
|
|
)>> : is_iterable<T> {};
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
struct is_container : std::disjunction<is_associative_container<T>, is_sequential_container<T>> {};
|
||
|
|
|
||
|
|
|
||
|
|
template<typename T, typename = void>
|
||
|
|
struct is_macro_enum : std::false_type {};
|
||
|
|
|
||
|
|
template<typename T>
|
||
|
|
struct is_macro_enum<T, std::void_t<decltype(
|
||
|
|
std::decay_t<T>::count,
|
||
|
|
std::decay_t<T>::names[0],
|
||
|
|
std::decay_t<T>::values[0]
|
||
|
|
)>> : std::is_enum<typename std::decay_t<T>::_enum> {};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
template<typename T, typename VariantT>
|
||
|
|
struct is_variant_member;
|
||
|
|
|
||
|
|
template<typename T, typename... Ts>
|
||
|
|
struct is_variant_member<T, std::variant<Ts...>> : std::disjunction<std::is_same<T, Ts>...> {};
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// true if is integral/floating point, or is constructible from and to string, or is macro enum
|
||
|
|
template<typename T>
|
||
|
|
struct is_basic_serializable : std::disjunction<
|
||
|
|
std::is_arithmetic<std::decay_t<T>>,
|
||
|
|
is_macro_enum<std::decay_t<T>>,
|
||
|
|
std::conjunction<std::is_constructible<string, T>, std::is_constructible<std::decay_t<T>, string>>> {};
|
||
|
|
}
|