@@ -34,8 +34,29 @@ 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 ,
57+ real_t <E> From = real_t <E>{},
58+ real_t <E> To = real_t <E>{}>
59+ requires (!UniqueRange<E> && !std::same_as<bool , real_t <E>>)
3960consteval std::pair<real_t <E>, real_t <E>> from_to ()
4061{
4162 if constexpr (std::is_signed_v<real_t <E>>
@@ -44,39 +65,40 @@ consteval std::pair<real_t<E>, real_t<E>> from_to()
4465 return from_to<E, From - 1 , To>();
4566 else if constexpr (!Name::name<E, static_cast <E>(To)>().empty ())
4667 return from_to<E, From, To + 1 >();
47- else
48- return {From, To};
68+ else {
69+ static_assert (From != To, " Not found any enum string" );
70+ return {From, To - 1 };
71+ }
4972}
5073
5174template <class E , int , int >
52- requires (std::same_as<bool , real_t <E>>)
75+ requires (!UniqueRange<E> && std::same_as<bool , real_t <E>>)
5376consteval std::pair<real_t <E>, real_t <E>> from_to ()
5477{
55- return {false , false };
78+ constexpr auto has_false =
79+ !Name::name<E, static_cast <E>(false )>().empty ();
80+ constexpr auto has_true =
81+ !Name::name<E, static_cast <E>(true )>().empty ();
82+ static_assert (has_false || has_true, " Not found any enum string" );
83+ return {!has_false, has_true};
5684}
5785
5886template <class E >
5987 requires (!std::same_as<bool , real_t <E>>)
6088consteval real_t <E> count ()
6189{
62- auto [from, to] = from_to<E, 0 , 0 >();
63- return static_cast <real_t <E>>(to - from);
90+ auto [from, to] = from_to<E>();
91+ return static_cast <real_t <E>>(to - from + 1 );
6492}
6593
6694template <class E >
6795 requires (std::same_as<bool , real_t <E>>)
6896consteval int count ()
6997{
70- return Name::name<E, static_cast <E>(false )>().empty ()
71- ? 0
72- : 1 + !Name::name<E, static_cast <E>(true )>().empty ();
98+ auto [from, to] = from_to<E>();
99+ return to - from + 1 ;
73100}
74101
75- template <class E >
76- concept UniqueNames = requires {
77- static_cast <std::string_view>(unique_enum_names (E{}));
78- };
79-
80102template <class E , class F = real_t <E>, F... Ix>
81103consteval auto whole_array (std::integer_sequence<F, Ix...> = {})
82104{
@@ -87,7 +109,7 @@ consteval auto whole_array(std::integer_sequence<F, Ix...> = {})
87109 return res;
88110 }
89111 else {
90- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
112+ constexpr auto first = Detail::from_to<E>().first ;
91113 std::array<char ,
92114 (Name::name<E, static_cast <E>(Ix + first)>().size () + ...
93115 + (sizeof ...(Ix) - 1 ))>
@@ -109,7 +131,7 @@ constexpr std::array enum_name_holder = Detail::whole_array<E>(
109131 Detail::count<E>()>{});
110132
111133template <class E >
112- constexpr std::array enum_name_holder<E, true > =
134+ constinit const std::array enum_name_holder<E, true > =
113135 Detail::whole_array<E, int >(
114136 std::make_integer_sequence<int , Detail::count<E>()>{});
115137
@@ -143,7 +165,7 @@ template <class E> constexpr std::array enum_names = get_names<E>();
143165template <class Type = std::string_view, class E >
144166Type enum_name (E name)
145167{
146- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
168+ constexpr auto first = Detail::from_to<E>().first ;
147169 constexpr auto n = std::size (enum_names<E>);
148170 if (static_cast <std::size_t >(
149171 static_cast <Detail::real_t <E>>(name) - first)
@@ -159,7 +181,7 @@ Type enum_name(E name)
159181
160182template <class E > constexpr E get_enum (const std::string_view &data)
161183{
162- constexpr auto first = Detail::from_to<E, 0 , 0 >().first ;
184+ constexpr auto first = Detail::from_to<E>().first ;
163185 Detail::real_t <E> ix{};
164186 for (auto v : enum_names<E>) {
165187 if (v == data) break ;
@@ -204,7 +226,7 @@ struct EnumArray : std::array<V, std::size(enum_names<E>)>
204226template <class E , class ... Args>
205227 requires (std::is_enum_v<E>
206228 && sizeof ...(Args) == Detail::count<E>()
207- && Detail::from_to<E, 0 , 0 >().first == 0 )
229+ && Detail::from_to<E>().first == 0 )
208230struct EnumVariant : std::variant<Args...>
209231{
210232 using base_variant = std::variant<Args...>;
0 commit comments