@@ -11,22 +11,75 @@ namespace stdx {
11
11
inline namespace v1 {
12
12
13
13
namespace detail {
14
- template <typename T, char ... Chars> CONSTEVAL auto decimal () -> T {
15
- static_assert ((... and (Chars >= ' 0' and Chars <= ' 9' )),
16
- " decimal numbers only are supported" );
17
- using U = decltype (stdx::to_underlying (std::declval<T>()));
18
- auto x = U{};
19
- ((x *= 10 , x += Chars - ' 0' ), ...);
20
- return T{x};
14
+ template <char C> constexpr static bool is_digit_sep_v = C == ' \' ' ;
15
+ template <char C>
16
+ constexpr static bool is_decimal_digit_v = C >= ' 0' and C <= ' 9' ;
17
+ template <char C>
18
+ constexpr static bool is_octal_digit_v = C >= ' 0' and C <= ' 7' ;
19
+ template <char C>
20
+ constexpr static bool is_binary_digit_v = C >= ' 0' and C <= ' 1' ;
21
+
22
+ template <char C>
23
+ constexpr static char force_lower_case = static_cast <unsigned char >(C) | 32u ;
24
+ template <char C>
25
+ constexpr static bool is_hex_digit_v =
26
+ (C >= ' 0' and C <= ' 9' ) or
27
+ (force_lower_case<C> >= ' a' and force_lower_case<C> <= ' f' );
28
+
29
+ template <char C>
30
+ constexpr static auto integral_value_v =
31
+ is_decimal_digit_v<C> ? C - ' 0' : force_lower_case<C> - ' a' + 10 ;
32
+
33
+ template <auto Base, char C, typename Sum>
34
+ CONSTEVAL auto maybe_add_digit (Sum s) {
35
+ if constexpr (not is_digit_sep_v<C>) {
36
+ s *= Base;
37
+ s += integral_value_v<C>;
38
+ }
39
+ return s;
21
40
}
41
+
42
+ template <auto Base, char ... Cs> struct raw_parser {
43
+ template <typename T> CONSTEVAL static auto parse () {
44
+ using U = decltype (stdx::to_underlying (std::declval<T>()));
45
+ auto x = U{};
46
+ ((x = maybe_add_digit<Base, Cs>(x)), ...);
47
+ return T{x};
48
+ }
49
+ };
50
+
51
+ template <char ... Cs> struct parser : raw_parser<10 , Cs...> {
52
+ static_assert ((... and (is_decimal_digit_v<Cs> or is_digit_sep_v<Cs>)));
53
+ };
54
+
55
+ template <char ... Cs> struct parser <' 0' , Cs...> : raw_parser<8 , Cs...> {
56
+ static_assert ((... and (is_octal_digit_v<Cs> or is_digit_sep_v<Cs>)));
57
+ };
58
+
59
+ template <char ... Cs> struct parser <' 0' , ' x' , Cs...> : raw_parser<16 , Cs...> {
60
+ static_assert ((... and (is_hex_digit_v<Cs> or is_digit_sep_v<Cs>)));
61
+ };
62
+ template <char ... Cs>
63
+ struct parser <' 0' , ' X' , Cs...> : parser<' 0' , ' x' , Cs...> {};
64
+
65
+ template <char ... Cs> struct parser <' 0' , ' b' , Cs...> : raw_parser<2 , Cs...> {
66
+ static_assert ((... and (is_binary_digit_v<Cs> or is_digit_sep_v<Cs>)));
67
+ };
68
+ template <char ... Cs>
69
+ struct parser <' 0' , ' B' , Cs...> : parser<' 0' , ' b' , Cs...> {};
22
70
} // namespace detail
23
71
72
+ template <typename T, char ... Chars> CONSTEVAL auto parse_literal () -> T {
73
+ using parser_t = detail::parser<Chars...>;
74
+ return parser_t ::template parse<T>();
75
+ }
76
+
24
77
template <auto I> using constant = std::integral_constant<decltype (I), I>;
25
78
template <auto I> constexpr static constant<I> _c{};
26
79
27
80
inline namespace literals {
28
81
template <char ... Chars> CONSTEVAL auto operator " " _c() {
29
- return _c<detail::decimal <std::uint32_t , Chars...>()>;
82
+ return _c<parse_literal <std::uint32_t , Chars...>()>;
30
83
}
31
84
} // namespace literals
32
85
0 commit comments