Files
2026-08-11 12:40:28 +08:00

86 lines
3.8 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<attribute_category_of_t<Head>, void> && 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>, void> && 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...>() && ...);
}
}