Bounded Unsigned Integer Type
Description
The bounded_uint<Min, Max> class template provides a safe unsigned integer type whose values are constrained to a compile-time range [Min, Max].
Any operation that would produce a value outside this range throws an exception at runtime.
The underlying storage type (basis_type) is automatically selected as the smallest safe unsigned integer type capable of representing Max:
| Max Value Range | Selected basis_type |
|---|---|
0 — 255 |
|
256 — 65,535 |
|
65,536 — 4,294,967,295 |
|
4,294,967,296 — 2^64 - 1 |
|
2^64 — 2^128 - 1 |
|
The template parameters Min and Max can be any non-bool unsigned type, including the library’s own safe unsigned types (u8, u16, etc.) or built-in unsigned types (std::uint8_t, unsigned int, etc.).
Max must be strictly greater than Min.
#include <boost/safe_numbers/bounded_integers.hpp>
namespace boost::safe_numbers {
template <auto Min, auto Max>
requires (detail::valid_bound<decltype(Min)> &&
detail::valid_bound<decltype(Max)> &&
detail::raw_value(Max) > detail::raw_value(Min))
class bounded_uint
{
public:
using basis_type = /* smallest safe unsigned type that fits Max */;
// Construction
explicit constexpr bounded_uint(basis_type val);
// Conversion to underlying types
template <typename OtherBasis>
explicit constexpr operator OtherBasis() const;
// Conversion to other bounded_uint types
template <auto Min2, auto Max2>
explicit constexpr operator bounded_uint<Min2, Max2>() const;
// Comparison operators
friend constexpr auto operator<=>(bounded_uint lhs, bounded_uint rhs) noexcept
-> std::strong_ordering = default;
// Compound assignment operators
constexpr auto operator+=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator-=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator*=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator/=(bounded_uint rhs) -> bounded_uint&;
// Increment and decrement operators
constexpr auto operator++() -> bounded_uint&;
constexpr auto operator++(int) -> bounded_uint;
constexpr auto operator--() -> bounded_uint&;
constexpr auto operator--(int) -> bounded_uint;
};
// Arithmetic operators (throw on out-of-bounds result)
template <auto Min, auto Max>
constexpr auto operator+(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator-(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator*(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator/(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator%(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
} // namespace boost::safe_numbers
Operator Behavior
Construction
explicit constexpr bounded_uint(basis_type val);
Constructs a bounded_uint from a value of the underlying basis_type.
The value is default-initialized to Min.
If val is less than Min or greater than Max, std::domain_error is thrown.
Conversion to Underlying Types
template <typename OtherBasis>
explicit constexpr operator OtherBasis() const;
Conversion to other unsigned integral types is explicit.
Widening conversions always succeed.
Narrowing conversions perform a runtime bounds check: if the value exceeds the maximum representable value of the target type, std::domain_error is thrown.
Conversion to Other Bounded Types
template <auto Min2, auto Max2>
explicit constexpr operator bounded_uint<Min2, Max2>() const;
Conversion to a bounded_uint with different bounds is explicit.
The target type’s constructor validates that the value falls within [Min2, Max2], throwing std::domain_error if it does not.
Comparison Operators
friend constexpr auto operator<=>(bounded_uint lhs, bounded_uint rhs) noexcept
-> std::strong_ordering = default;
Full three-way comparison is supported via operator<=>, which returns std::strong_ordering.
All comparison operators (<, ⇐, >, >=, ==, !=) are available.
Arithmetic Operators
template <auto Min, auto Max>
constexpr auto operator+(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator-(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator*(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator/(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
template <auto Min, auto Max>
constexpr auto operator%(bounded_uint<Min, Max> lhs,
bounded_uint<Min, Max> rhs) -> bounded_uint<Min, Max>;
Arithmetic is performed on the underlying basis_type values.
The result is then used to construct a new bounded_uint, which validates that it falls within [Min, Max].
If the result is out of bounds, the exception thrown depends on the underlying safe unsigned integer operation:
-
+: Throwsstd::overflow_errorif the result exceedsMax -
-: Throwsstd::underflow_errorif the result would be belowMin -
*: Throwsstd::overflow_errorif the result exceedsMax -
/: Throwsstd::domain_errorif dividing by zero, orstd::domain_errorif the result falls outside[Min, Max] -
%: Throwsstd::domain_errorif the divisor is zero, orstd::domain_errorif the result falls outside[Min, Max]
Compound Assignment Operators
constexpr auto operator+=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator-=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator*=(bounded_uint rhs) -> bounded_uint&;
constexpr auto operator/=(bounded_uint rhs) -> bounded_uint&;
Compound assignment operators delegate to their corresponding arithmetic operators and follow the same exception behavior.
Increment and Decrement Operators
constexpr auto operator++() -> bounded_uint&;
constexpr auto operator++(int) -> bounded_uint;
constexpr auto operator--() -> bounded_uint&;
constexpr auto operator--(int) -> bounded_uint;
-
++(pre/post): Adds one to the underlying value and validates the result. Throwsstd::overflow_errorif the value is already atMax, orstd::domain_errorif the incremented value exceeds the upper bound. -
--(pre/post): Subtracts one from the underlying value and validates the result. Throwsstd::underflow_errorif the value is already atMin, orstd::domain_errorif the decremented value falls below the lower bound.