You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The library provides user-defined literal suffixes for concise construction of safe integer types.
13
+
The library provides user-defined literal suffixes for concise construction of safe numeric types.
14
14
The literals are defined in the `boost::safe_numbers::literals` namespace.
15
-
The behavior of the literals depends on the type:
15
+
The behavior of each literal depends on the target type:
16
16
17
17
- For `_u8`, `_u16`, and `_u32`, the literal value is range-checked and throws `std::overflow_error` if the value exceeds the target type's maximum.
18
18
- The `_u64` literal performs no range check since `unsigned long long` maps directly to `std::uint64_t` (statically verified).
19
-
- The `_u128` literal parses a string representation and throws `std::overflow_error` on overflow or `std::invalid_argument` on invalid input.
19
+
- The `_u128` literal accepts an integer-form token, parses the digit string, and throws `std::overflow_error` on overflow or `std::invalid_argument` on invalid input.
20
+
- For `_i8`, `_i16`, `_i32`, and `_i64`, the literal magnitude is range-checked against the signed maximum and throws `std::overflow_error` if it exceeds it.
21
+
Negative values are formed by applying the wrapper's unary `operator-` to the positive literal: the expression `-42_i32` parses as `-(42_i32)`.
22
+
- The `_i128` literal mirrors `_u128`: it parses an integer-form digit string into `int128_t` and throws on overflow or invalid input.
23
+
- For `_f32` and `_f64`, the literal is taken as `long double` and range-checked against the target's maximum, throwing `std::overflow_error` on overflow.
20
24
21
25
[source,c++]
22
26
----
@@ -30,6 +34,15 @@ constexpr auto operator ""_u32(unsigned long long int val) -> u32;
30
34
constexpr auto operator ""_u64(unsigned long long int val) noexcept -> u64;
31
35
constexpr auto operator ""_u128(const char* str) -> u128;
32
36
37
+
constexpr auto operator ""_i8(unsigned long long int val) -> i8;
38
+
constexpr auto operator ""_i16(unsigned long long int val) -> i16;
39
+
constexpr auto operator ""_i32(unsigned long long int val) -> i32;
40
+
constexpr auto operator ""_i64(unsigned long long int val) -> i64;
41
+
constexpr auto operator ""_i128(const char* str) -> i128;
42
+
43
+
constexpr auto operator ""_f32(long double val) -> f32;
44
+
constexpr auto operator ""_f64(long double val) -> f64;
| Parses string; throws `std::overflow_error` on overflow, `std::invalid_argument` on invalid input
72
+
| Parses digit string; throws `std::overflow_error` on overflow, `std::invalid_argument` on invalid input
73
+
74
+
| `_i8`
75
+
| `i8`
76
+
| Throws `std::overflow_error` if magnitude > 127
77
+
78
+
| `_i16`
79
+
| `i16`
80
+
| Throws `std::overflow_error` if magnitude > 32,767
81
+
82
+
| `_i32`
83
+
| `i32`
84
+
| Throws `std::overflow_error` if magnitude > 2,147,483,647
85
+
86
+
| `_i64`
87
+
| `i64`
88
+
| Throws `std::overflow_error` if magnitude > 9,223,372,036,854,775,807
89
+
90
+
| `_i128`
91
+
| `i128`
92
+
| Parses digit string; throws `std::overflow_error` on overflow, `std::invalid_argument` on invalid input
93
+
94
+
| `_f32`
95
+
| `f32`
96
+
| Throws `std::overflow_error` if value > `std::numeric_limits<float>::max()`
97
+
98
+
| `_f64`
99
+
| `f64`
100
+
| Throws `std::overflow_error` if value > `std::numeric_limits<double>::max()`
60
101
|===
61
102
62
103
== Usage
@@ -72,14 +113,37 @@ constexpr auto b {1000_u16};
72
113
constexpr auto c {100000_u32};
73
114
constexpr auto d {9999999999_u64};
74
115
constexpr auto e {340282366920938463463374607431768211455_u128};
116
+
117
+
constexpr auto f {-42_i8};
118
+
constexpr auto g {32767_i16};
119
+
constexpr auto h {-2147483647_i32};
120
+
constexpr auto i {9223372036854775807_i64};
121
+
constexpr auto j {-170141183460469231731687303715884105727_i128};
122
+
123
+
constexpr auto k {3.14_f32};
124
+
constexpr auto l {2.718281828459045_f64};
75
125
----
76
126
77
127
Literals are `constexpr` and can be used in compile-time contexts.
78
128
When used in a `constexpr` context, an out-of-range value produces a compile error rather than a runtime exception.
79
129
130
+
== Negative Signed Literals
131
+
132
+
C++ user-defined literal operators never see a leading minus sign as part of their input.
133
+
The expression `-42_i32` is parsed as `-(42_i32)`: the literal returns a positive `i32` and unary `operator-` on the wrapper produces the negative result.
134
+
Because the literal's range check is against the positive maximum (`INT_MAX`), the asymmetric `INT_MIN` value is not directly expressible through the literal: writing `-128_i8` parses as `-(128_i8)`, and the inner literal throws because `128 > INT8_MAX`.
135
+
Use direct construction for that one value:
136
+
137
+
[source,c++]
138
+
----
139
+
constexpr auto min_i8 {i8{std::numeric_limits<std::int8_t>::min()}};
140
+
----
141
+
142
+
The same asymmetry applies to `_i16`, `_i32`, `_i64`, and `_i128`.
143
+
80
144
== Examples
81
145
82
-
.This https://github.com/boostorg/safe_numbers/blob/develop/examples/literals.cpp[example] demonstrates how to use user-defined literals with safe integer types.
146
+
.This https://github.com/boostorg/safe_numbers/blob/develop/examples/literals.cpp[example] demonstrates how to use user-defined literals with safe numeric types.
0 commit comments