86 lines
3.7 KiB
C++
86 lines
3.7 KiB
C++
#pragma once
|
|
#include <concepts>
|
|
#include <cstddef>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
namespace structive {
|
|
template <class... Types>
|
|
struct Type_List {};
|
|
template <class Type, class List>
|
|
struct Type_List_Contains;
|
|
template <class Type, class... Types>
|
|
struct Type_List_Contains<Type, Type_List<Types...>> : std::bool_constant<(std::same_as<Type, Types> || ...)> {};
|
|
template <class Type, class List>
|
|
inline constexpr bool type_list_contains_v = Type_List_Contains<Type, List>::value;
|
|
template <class List, class Type>
|
|
struct Type_List_Push_Unique;
|
|
template <class... Types, class Type>
|
|
struct Type_List_Push_Unique<Type_List<Types...>, Type> {
|
|
using type = std::conditional_t<(std::same_as<Type, Types> || ...), Type_List<Types...>, Type_List<Types..., Type>>;
|
|
};
|
|
template <class Input, class Output = Type_List<>>
|
|
struct Type_List_Unique;
|
|
template <class Output>
|
|
struct Type_List_Unique<Type_List<>, Output> {
|
|
using type = Output;
|
|
};
|
|
template <class Head, class... Tail, class Output>
|
|
struct Type_List_Unique<Type_List<Head, Tail...>, Output> {
|
|
using next = typename Type_List_Push_Unique<Output, Head>::type;
|
|
using type = typename Type_List_Unique<Type_List<Tail...>, next>::type;
|
|
};
|
|
template <class Type, class List>
|
|
struct Type_List_Index;
|
|
template <class Type, class... Tail>
|
|
struct Type_List_Index<Type, Type_List<Type, Tail...>> : std::integral_constant<std::size_t, 0> {};
|
|
template <class Type, class Head, class... Tail>
|
|
struct Type_List_Index<Type, Type_List<Head, Tail...>> : std::integral_constant<std::size_t, 1 + Type_List_Index<Type, Type_List<Tail...>>::value> {};
|
|
template <class Type, class List>
|
|
inline constexpr std::size_t type_list_index_v = Type_List_Index<Type, List>::value;
|
|
template <class Attribute, class = void>
|
|
struct Attribute_Category_Of {
|
|
using type = void;
|
|
};
|
|
template <class Attribute>
|
|
struct Attribute_Category_Of<Attribute, std::void_t<typename Attribute::attribute_category>> {
|
|
using type = typename Attribute::attribute_category;
|
|
};
|
|
template <class Attribute>
|
|
using attribute_category_of_t = typename Attribute_Category_Of<Attribute>::type;
|
|
template <class Category, class... Attributes>
|
|
struct Find_Attribute_By_Category;
|
|
template <class Category>
|
|
struct Find_Attribute_By_Category<Category> {
|
|
using type = void;
|
|
};
|
|
template <class Category, class Head, class... Tail>
|
|
struct Find_Attribute_By_Category<Category, Head, Tail...> {
|
|
using type = std::conditional_t<std::same_as<Category, attribute_category_of_t<Head>>, Head, typename Find_Attribute_By_Category<Category, Tail...>::type>;
|
|
};
|
|
template <class Category, class List>
|
|
struct Find_Attribute_In_List;
|
|
template <class Category, class... Attributes>
|
|
struct Find_Attribute_In_List<Category, Type_List<Attributes...>> {
|
|
using type = typename Find_Attribute_By_Category<Category, Attributes...>::type;
|
|
};
|
|
template <class Category, class List>
|
|
using find_attribute_in_list_t = typename Find_Attribute_In_List<Category, List>::type;
|
|
template <class Category, class... Attributes>
|
|
consteval std::size_t count_attribute_category() {
|
|
return (std::size_t{0} + ... + (std::same_as<attribute_category_of_t<Attributes>, Category> ? 1u : 0u));
|
|
}
|
|
template <class Attribute, class... Attributes>
|
|
consteval bool unique_single_value_category_for() {
|
|
if constexpr (requires { Attribute::single_valued; }) {
|
|
if constexpr (Attribute::single_valued && !std::same_as<attribute_category_of_t<Attribute>, void>) {
|
|
return count_attribute_category<attribute_category_of_t<Attribute>, Attributes...>() == 1;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
template <class... Attributes>
|
|
consteval bool unique_single_value_categories() {
|
|
return (unique_single_value_category_for<Attributes, Attributes...>() && ...);
|
|
}
|
|
}
|