16#include <source_location>
19#include <gmp/meta/detail/member_ref.hpp>
40 static constexpr int min = -128;
41 static constexpr int max = 127;
57#define GMP_ENUM_RANGE(Enum, Min, Max) \
59 struct gmp::enum_traits<Enum> { \
60 static constexpr int min = Min; \
61 static constexpr int max = Max; \
74#define GMP_ENUM_VALUES(Enum, ...) \
76 struct gmp::enum_traits<Enum> { \
77 static constexpr auto values = std::to_array({__VA_ARGS__}); \
101concept has_enum_values =
111template<
typename E, fixed_
string P, auto V>
112consteval bool is_valid_enum_value() {
114 return name.find(
P.data()) != std::string_view::npos;
118consteval auto enum_values_scan(std::index_sequence<I...>) {
121 std::array<E, count>
result{};
122 std::size_t index = 0;
124 auto append = [&]<
int V>()
consteval {
126 result[index++] =
static_cast<E>(
V);
156 static_assert(std::is_enum_v<E>,
"enum_values<E>() requires E to be an enum type");
158 if constexpr (detail::has_enum_values<E>) {
164 static_assert(min <= max,
"enum_traits<E>::min must be <= max");
166 return detail::enum_values_scan<E, P, min>(
167 std::make_index_sequence<
static_cast<std::size_t
>(max - min + 1)>{}
202 static_assert(std::is_enum_v<E>,
"enum_count<E>() requires E to be an enum type");
234template<
auto E, fixed_string
P = fixed_string(
"::")>
236 constexpr auto name = detail::value_name_of<E>();
238 if constexpr (
start != std::string_view::npos) {
239#if GMP_COMPILER_CLANG || GMP_COMPILER_GCC
240 constexpr auto end =
name.find_last_of(
"]");
242 constexpr auto end =
name.find_last_of(
">");
293 constexpr std::size_t size = values.size();
295 if constexpr (size == 0) {
296 return std::array<std::string_view, 0>{};
298 return [&]<std::size_t...
Is>(std::index_sequence<
Is...>) {
299 return std::array<std::string_view, size>{
302 }(std::make_index_sequence<size>{});
320 constexpr std::size_t size = values.size();
322 if constexpr (size == 0) {
323 return std::array<std::pair<E, std::string_view>, 0>{};
325 return [&]<std::size_t...
Is>(std::index_sequence<
Is...>) {
326 return std::array<std::pair<E, std::string_view>, size>{
327 std::pair<E, std::string_view>{ values[
Is],
names[
Is] }...
329 }(std::make_index_sequence<size>{});
344 for (std::size_t
i = 0;
i < values.size(); ++
i) {
345 if (values[
i] == value) {
363 for (
const auto& [value,
n] :
entries) {
400template<
typename T,
typename...
Args>
401 requires std::is_aggregate_v<std::remove_cvref_t<T>>
407 return sizeof...(Args) - 1;
463template<std::
size_t I,
typename T>
464 requires std::is_aggregate_v<T> &&
473template<std::
size_t I,
typename T>
475 static_assert(std::is_aggregate_v<T>,
"member_name() can only be used with aggregate types.");
541 if constexpr (size == 0) {
542 return std::array<std::string_view, 0>{};
544 return []<std::size_t...
Is>(std::index_sequence<
Is...>) {
545 return (std::array<std::string_view, size> {
548 }(std::make_index_sequence<size>{});
567template<std::
size_t I,
typename T>
576struct member_type_names_holder {
579 static constexpr auto fixed_names = []<std::size_t...
Is>(std::index_sequence<
Is...>) {
581 }(std::make_index_sequence<N>{});
583 static constexpr auto views = []<std::size_t...
Is>(std::index_sequence<
Is...>) {
584 return std::array<std::string_view, N>{
585 std::get<Is>(fixed_names).to_string_view()...
587 }(std::make_index_sequence<N>{});
626 return detail::member_type_names_holder<T>::views;
641template<std::
size_t I,
typename T,
typename UnqualifiedT = std::remove_cvref_t<T>>
642 requires std::is_aggregate_v<UnqualifiedT>
650template<std::
size_t I,
typename T,
typename UnqualifiedT = std::remove_cvref_t<T>>
652 static_assert(std::is_aggregate_v<UnqualifiedT>,
"member_ref() can only be used with aggregate types.");
660#define GMP_FOR_EACH_MEMBER_DEFINE(N) \
661 template<typename T, typename F> \
662 void for_each_member_impl(T&& value, F&& f, constant_arg_t<N>) noexcept { \
663 auto&& [GMP_GET_FIRST_N(N, GMP_IDENTIFIERS)] = value; \
664 auto members = std::forward_as_tuple(GMP_GET_FIRST_N(N, GMP_IDENTIFIERS)); \
665 constexpr auto mem_names = gmp::member_names<T>(); \
666 std::size_t index = 0; \
668 [&](auto&&... member) { (f(mem_names[index++], std::forward<decltype(member)>(member)), ...); }, members); \
671#if GMP_STANDARD_PREPROCESSOR
679#undef GMP_FOR_EACH_MEMBER_DEFINE
695template<
typename T,
typename F>
696 requires std::is_aggregate_v<std::remove_cvref_t<T>>
698 detail::for_each_member_impl(
699 std::forward<T>(value),
700 std::forward<F>(
func),
706template<
typename T,
typename F>
708 static_assert(std::is_aggregate_v<std::remove_cvref_t<T>>,
709 "for_each_member() can only be used with aggregate types.");
constexpr constant_arg_t< V > constant_arg
A ready-to-use constant_arg_t<V> object for a compile-time value.
A placeholder type implicitly convertible to any type.
Customize the reflection range or explicit values for an enumeration.
A compile-time string type with fixed length and constexpr operations.
Format a type name for documentation-friendly display.