@@ -34,8 +34,27 @@ namespace Detail
3434{
3535template <class T > using real_t = std::underlying_type_t <T>;
3636
37- template <class E , real_t <E> From, real_t <E> To>
38- requires (!std::same_as<bool , real_t <E>>)
37+ template <class E >
38+ concept UniqueNames = requires {
39+ static_cast <std::string_view>(unique_enum_names (E{}));
40+ };
41+
42+ template <class E >
43+ concept UniqueRange = requires {
44+ static_cast <std::pair<real_t <E>, real_t <E>>>(unique_from_to (E{}));
45+ };
46+
47+ template <class E >
48+ requires (UniqueRange<E>)
49+ consteval std::pair<real_t <E>, real_t <E>> from_to ()
50+ {
51+ constexpr auto res = unique_from_to (E{});
52+ static_assert (res.first <= res.second , " Invalid range" );
53+ return res;
54+ }
55+
56+ template <class E , real_t <E> From = {}, real_t <E> To = {}>
57+ requires (!UniqueRange<E> && !std::same_as<bool , real_t <E>>)
3958consteval std::pair<real_t <E>, real_t <E>> from_to ()
4059{
4160 if constexpr (std::is_signed_v<real_t <E>>
@@ -44,39 +63,40 @@ consteval std::pair<real_t<E>, real_t<E>> from_to()
4463 return from_to<E, From - 1 , To>();
4564 else if constexpr (!Name::name<E, static_cast <E>(To)>().empty ())
4665 return from_to<E, From, To + 1 >();
47- else
48- return {From, To};
66+ else {
67+ static_assert (From != To, " Not found any enum string" );
68+ return {From, To - 1 };
69+ }
4970}
5071
5172template <class E , int , int >
52- requires (std::same_as<bool , real_t <E>>)
73+ requires (!UniqueRange<E> && std::same_as<bool , real_t <E>>)
5374consteval std::pair<real_t <E>, real_t <E>> from_to ()
5475{
55- return {false , false };
76+ constexpr auto has_false =
77+ !Name::name<E, static_cast <E>(false )>().empty ();
78+ constexpr auto has_true =
79+ !Name::name<E, static_cast <E>(true )>().empty ();
80+ static_assert (has_false || has_true, " Not found any enum string" );
81+ return {!has_false, has_true};
5682}
5783
5884template <class E >
5985 requires (!std::same_as<bool , real_t <E>>)
6086consteval real_t <E> count ()
6187{
62- auto [from, to] = from_to<E, 0 , 0 >();
63- return static_cast <real_t <E>>(to - from);
88+ auto [from, to] = from_to<E>();
89+ return static_cast <real_t <E>>(to - from + 1 );
6490}
6591
6692template <class E >
6793 requires (std::same_as<bool , real_t <E>>)
6894consteval int count ()
6995{
70- return Name::name<E, static_cast <E>(false )>().empty ()
71- ? 0
72- : 1 + !Name::name<E, static_cast <E>(true )>().empty ();
96+ auto [from, to] = from_to<E>();
97+ return to - from + 1 ;
7398}
7499
75- template <class E >
76- concept UniqueNames = requires {
77- static_cast <std::string_view>(unique_enum_names (E{}));
78- };
79-
80100template <class E , class F = real_t <E>, F... Ix>
81101consteval auto whole_array (std::integer_sequence<F, Ix...> = {})
82102{
@@ -87,7 +107,7 @@ consteval auto whole_array(std::integer_sequence<F, Ix...> = {})
87107 return res;
88108 }
89109 else {
90- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
110+ constexpr auto first = Detail::from_to<E>().first ;
91111 std::array<char ,
92112 (Name::name<E, static_cast <E>(Ix + first)>().size () + ...
93113 + (sizeof ...(Ix) - 1 ))>
@@ -109,7 +129,7 @@ constexpr std::array enum_name_holder = Detail::whole_array<E>(
109129 Detail::count<E>()>{});
110130
111131template <class E >
112- constexpr std::array enum_name_holder<E, true > =
132+ constinit const std::array enum_name_holder<E, true > =
113133 Detail::whole_array<E, int >(
114134 std::make_integer_sequence<int , Detail::count<E>()>{});
115135
@@ -143,7 +163,7 @@ template <class E> constexpr std::array enum_names = get_names<E>();
143163template <class Type = std::string_view, class E >
144164Type enum_name (E name)
145165{
146- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
166+ constexpr auto first = Detail::from_to<E>().first ;
147167 constexpr auto n = std::size (enum_names<E>);
148168 if (static_cast <std::size_t >(
149169 static_cast <Detail::real_t <E>>(name) - first)
@@ -159,7 +179,7 @@ Type enum_name(E name)
159179
160180template <class E > constexpr E get_enum (const std::string_view &data)
161181{
162- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
182+ constexpr auto first = Detail::from_to<E>().first ;
163183 Detail::real_t <E> ix{};
164184 for (auto v : enum_names<E>) {
165185 if (v == data) break ;
@@ -204,7 +224,7 @@ struct EnumArray : std::array<V, std::size(enum_names<E>)>
204224template <class E , class ... Args>
205225 requires (std::is_enum_v<E>
206226 && sizeof ...(Args) == Detail::count<E>()
207- && Detail::from_to<E, 0 , 0 >().first == 0 )
227+ && Detail::from_to<E>().first == 0 )
208228struct EnumVariant : std::variant<Args...>
209229{
210230 using base_variant = std::variant<Args...>;
0 commit comments