Skip to content

Commit b4d46ca

Browse files
committed
Convert static_assert in fly::literals::numeric_literals to use a concept
1 parent 30de232 commit b4d46ca

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

fly/types/numeric/detail/literal_parser.hpp

+29-13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,29 @@
66

77
namespace fly::detail {
88

9+
/**
10+
* Concept that is satisfied if the provided character is a valid literal for the provided base.
11+
*/
12+
template <std::size_t Base, char Literal>
13+
concept ValidLiteralForBase = (Literal == '\'') ||
14+
((Base == 2) && ((Literal >= '0') && (Literal <= '1'))) ||
15+
((Base == 8) && ((Literal >= '0') && (Literal <= '7'))) ||
16+
((Base == 10) && ((Literal >= '0') && (Literal <= '9'))) ||
17+
((Base == 16) && ((Literal >= '0') && (Literal <= '9'))) ||
18+
((Base == 16) && ((Literal >= 'A') && (Literal <= 'F'))) ||
19+
((Base == 16) && ((Literal >= 'a') && (Literal <= 'f')));
20+
21+
/**
22+
* Concept that is satisfied if the provided value fits within the limits of the desired type to be
23+
* converted to.
24+
*/
25+
template <typename From, typename To, From Value>
26+
concept ValueWithinLimits = requires
27+
{
28+
requires(Value >= std::numeric_limits<To>::min());
29+
requires(Value <= std::numeric_limits<To>::max());
30+
};
31+
932
/**
1033
* Structures to recursively aggregate the value of an integer literal as it is being parsed.
1134
*
@@ -14,7 +37,11 @@ namespace fly::detail {
1437
* @tparam Literals Variadic list of characters to parse.
1538
*/
1639
template <typename T, T Base, char... Literals>
40+
// clang-format off
41+
// Formatter disabled because it doesn't handle this constraint well.
42+
requires(ValidLiteralForBase<Base, Literals> && ...)
1743
struct Aggregator;
44+
// clang-format on
1845

1946
// Specialization to convert the current character being parsed to an integer and recurse on the
2047
// remainder of the characters.
@@ -36,15 +63,6 @@ struct Aggregator<T, Base, Digit, Literals...>
3663
*/
3764
static constexpr T parse_and_validate_literal()
3865
{
39-
constexpr bool literal_is_valid_for_base =
40-
((Base == 2) && ((Digit >= '0') && (Digit <= '1'))) ||
41-
((Base == 8) && ((Digit >= '0') && (Digit <= '7'))) ||
42-
((Base == 10) && ((Digit >= '0') && (Digit <= '9'))) ||
43-
((Base == 16) && ((Digit >= '0') && (Digit <= '9'))) ||
44-
((Base == 16) && ((Digit >= 'A') && (Digit <= 'F'))) ||
45-
((Base == 16) && ((Digit >= 'a') && (Digit <= 'f')));
46-
static_assert(literal_is_valid_for_base, "Invalid literal for base");
47-
4866
if constexpr ((Digit >= 'A') && (Digit <= 'F'))
4967
{
5068
return static_cast<T>(Digit) - static_cast<T>('A') + 0xA;
@@ -137,7 +155,7 @@ struct Parser<T, '0', 'X', Literals...> : ParserBase<T, 16, Literals...>
137155
};
138156

139157
/**
140-
* Validate that a value can be converted to a desired type and perform that conversion
158+
* Validate that a value can be converted to a desired type and perform that conversion.
141159
*
142160
* @tparam From The current integer literal type.
143161
* @tparam To The desired integer literal type.
@@ -146,11 +164,9 @@ struct Parser<T, '0', 'X', Literals...> : ParserBase<T, 16, Literals...>
146164
* @return The converted integer literal.
147165
*/
148166
template <typename From, typename To, From Value>
167+
requires ValueWithinLimits<From, To, Value>
149168
constexpr To validate_and_convert()
150169
{
151-
static_assert(Value >= std::numeric_limits<To>::min(), "Literal overflow");
152-
static_assert(Value <= std::numeric_limits<To>::max(), "Literal overflow");
153-
154170
return static_cast<To>(Value);
155171
}
156172

0 commit comments

Comments
 (0)