From c4070a79ddef4a159b825370ee70c6daec43515f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 24 Feb 2026 10:08:14 -0500 Subject: [PATCH 1/5] Remove the verified types --- .../detail/verified_type_basis.hpp | 377 ------------------ .../boost/safe_numbers/verified_integers.hpp | 29 -- 2 files changed, 406 deletions(-) delete mode 100644 include/boost/safe_numbers/detail/verified_type_basis.hpp delete mode 100644 include/boost/safe_numbers/verified_integers.hpp diff --git a/include/boost/safe_numbers/detail/verified_type_basis.hpp b/include/boost/safe_numbers/detail/verified_type_basis.hpp deleted file mode 100644 index 3d342fb..0000000 --- a/include/boost/safe_numbers/detail/verified_type_basis.hpp +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_SAFE_NUMBERS_VERIFIED_INTEGER_BASIS_HPP -#define BOOST_SAFE_NUMBERS_VERIFIED_INTEGER_BASIS_HPP - -#include -#include -#include -#include - -#ifndef BOOST_SAFE_NUMBERS_BUILD_MODULE - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // BOOST_SAFE_NUMBERS_BUILD_MODULE - -namespace boost::safe_numbers::detail { - -template -class verified_type_basis -{ -private: - - using underlying_type = underlying_type_t; - - BasisType basis_ {}; - -public: - - consteval verified_type_basis() = default; - - explicit consteval verified_type_basis(const BasisType basis) : basis_{basis} {} - - explicit consteval verified_type_basis(const underlying_type val) : verified_type_basis{BasisType{val}} {} - - [[nodiscard]] explicit constexpr operator BasisType() const noexcept { return basis_; } - - [[nodiscard]] explicit constexpr operator underlying_type() const noexcept { return static_cast(basis_); } - - [[nodiscard]] friend constexpr auto operator<=>(verified_type_basis lhs, verified_type_basis rhs) noexcept - -> std::strong_ordering = default; - - consteval auto operator+=(verified_type_basis rhs) -> verified_type_basis&; - - consteval auto operator-=(verified_type_basis rhs) -> verified_type_basis&; - - consteval auto operator*=(verified_type_basis rhs) -> verified_type_basis&; - - consteval auto operator/=(verified_type_basis rhs) -> verified_type_basis&; - - consteval auto operator%=(verified_type_basis rhs) -> verified_type_basis&; - - consteval auto operator++() -> verified_type_basis&; - - consteval auto operator++(int) -> verified_type_basis; - - consteval auto operator--() -> verified_type_basis&; - - consteval auto operator--(int) -> verified_type_basis; -}; - -template -[[nodiscard]] consteval auto operator+(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis -{ - return verified_type_basis{static_cast(lhs) + static_cast(rhs)}; -} - -template -[[nodiscard]] consteval auto operator-(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis -{ - return verified_type_basis{static_cast(lhs) - static_cast(rhs)}; -} - -template -[[nodiscard]] consteval auto operator*(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis -{ - return verified_type_basis{static_cast(lhs) * static_cast(rhs)}; -} - -template -[[nodiscard]] consteval auto operator/(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis -{ - return verified_type_basis{static_cast(lhs) / static_cast(rhs)}; -} - -template -[[nodiscard]] consteval auto operator%(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis -{ - return verified_type_basis{static_cast(lhs) % static_cast(rhs)}; -} - -template -consteval auto verified_type_basis::operator+=(verified_type_basis rhs) -> verified_type_basis& -{ - *this = *this + rhs; - return *this; -} - -template -consteval auto verified_type_basis::operator-=(verified_type_basis rhs) -> verified_type_basis& -{ - *this = *this - rhs; - return *this; -} - -template -consteval auto verified_type_basis::operator*=(verified_type_basis rhs) -> verified_type_basis& -{ - *this = *this * rhs; - return *this; -} - -template -consteval auto verified_type_basis::operator/=(verified_type_basis rhs) -> verified_type_basis& -{ - *this = *this / rhs; - return *this; -} - -template -consteval auto verified_type_basis::operator%=(verified_type_basis rhs) -> verified_type_basis& -{ - *this = *this % rhs; - return *this; -} - -template -consteval auto verified_type_basis::operator++() -> verified_type_basis& -{ - ++basis_; - return *this; -} - -template -consteval auto verified_type_basis::operator++(int) -> verified_type_basis -{ - auto tmp = *this; - ++(*this); - return tmp; -} - -template -consteval auto verified_type_basis::operator--() -> verified_type_basis& -{ - --basis_; - return *this; -} - -template -consteval auto verified_type_basis::operator--(int) -> verified_type_basis -{ - auto tmp = *this; - --(*this); - return tmp; -} - -// Mixed-type operation guards: produce clear static_assert messages -// instead of cryptic "invalid operands to binary expression" errors. - -#define BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP(OP_NAME, OP_SYMBOL) \ -template \ - requires (!std::is_same_v) \ -consteval auto OP_SYMBOL(const verified_type_basis, \ - const verified_type_basis) \ -{ \ - static_assert(dependent_false, \ - "Can not perform " OP_NAME " between verified types with different basis types"); \ - return verified_type_basis(LHSBasis{}); \ -} - -BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP("addition", operator+) -BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP("subtraction", operator-) -BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP("multiplication", operator*) -BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP("division", operator/) -BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP("modulo", operator%) - -#undef BOOST_SAFE_NUMBERS_DEFINE_MIXED_VERIFIED_OP - -// Mixed-type comparison guard -template - requires (!std::is_same_v) -constexpr auto operator<=>(const verified_type_basis, - const verified_type_basis) - -> std::strong_ordering -{ - static_assert(dependent_false, - "Can not compare verified types with different basis types"); - return std::strong_ordering::equal; -} - -template - requires (!std::is_same_v) -constexpr auto operator==(const verified_type_basis, - const verified_type_basis) - -> bool -{ - static_assert(dependent_false, - "Can not compare verified types with different basis types"); - return false; -} - -// At runtime, we want to enable mixed operations between verified and unverified values of the same width -// e.g., u32 + verified_u32 = u32 or u32 <=> verified_u32 -// These operations will always result in the runtime value - -#define BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(op) \ -template \ -constexpr auto operator op(const verified_type_basis lhs, \ - const VerifiedBasisType rhs) -> VerifiedBasisType \ -{ \ - return static_cast(lhs) op rhs; \ -} \ - \ -template \ -constexpr auto operator op(const VerifiedBasisType lhs, \ - const verified_type_basis rhs) -> VerifiedBasisType \ -{ \ - return lhs op static_cast(rhs); \ -} \ - \ -template \ -constexpr auto operator op(const verified_type_basis lhs, \ - const OtherBasis rhs) -> VerifiedBasisType \ -{ \ - return static_cast(lhs) op rhs; \ -} \ - \ -template \ -constexpr auto operator op(const OtherBasis lhs, \ - const verified_type_basis rhs) -> VerifiedBasisType \ -{ \ - return static_cast(lhs) op rhs; \ -} - -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(+) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(-) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(*) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(/) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR(%) - -#undef BOOST_SAFE_NUMBERS_MIXED_VERIFIED_OPERATOR - -// Bitwise mixed operators (&, |, ^) need separate treatment because the native -// unsigned_integer_basis bitwise operators live in boost::safe_numbers (not detail), -// so ADL cannot find them from within detail. We operate on raw values directly. - -#define BOOST_SAFE_NUMBERS_MIXED_VERIFIED_BITWISE_OPERATOR(op) \ -template \ -constexpr auto operator op(const verified_type_basis lhs, \ - const VerifiedBasisType rhs) -> VerifiedBasisType \ -{ \ - using raw = underlying_type_t; \ - return VerifiedBasisType{static_cast( \ - raw_value(static_cast(lhs)) op raw_value(rhs))}; \ -} \ - \ -template \ -constexpr auto operator op(const VerifiedBasisType lhs, \ - const verified_type_basis rhs) -> VerifiedBasisType \ -{ \ - using raw = underlying_type_t; \ - return VerifiedBasisType{static_cast( \ - raw_value(lhs) op raw_value(static_cast(rhs)))}; \ -} - -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_BITWISE_OPERATOR(&) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_BITWISE_OPERATOR(|) -BOOST_SAFE_NUMBERS_MIXED_VERIFIED_BITWISE_OPERATOR(^) - -#undef BOOST_SAFE_NUMBERS_MIXED_VERIFIED_BITWISE_OPERATOR - -// Shift mixed operators (<<, >>) call shl_impl/shr_impl directly (in detail namespace) - -template -constexpr auto operator<<(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> VerifiedBasisType -{ - return shl_impl(static_cast(lhs), rhs); -} - -template -constexpr auto operator<<(const VerifiedBasisType lhs, - const verified_type_basis rhs) -> VerifiedBasisType -{ - return shl_impl(lhs, static_cast(rhs)); -} - -template -constexpr auto operator>>(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> VerifiedBasisType -{ - return shr_impl(static_cast(lhs), rhs); -} - -template -constexpr auto operator>>(const VerifiedBasisType lhs, - const verified_type_basis rhs) -> VerifiedBasisType -{ - return shr_impl(lhs, static_cast(rhs)); -} - -// Separate implementations for the comparisons since we can't shoehorn them into the macros above - -template -constexpr auto operator<=>(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> std::strong_ordering -{ - return static_cast(lhs) <=> rhs; -} - -template -constexpr auto operator==(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> bool -{ - return static_cast(lhs) == rhs; -} - -template -constexpr auto operator<=>(const VerifiedBasisType lhs, - const verified_type_basis rhs) -> std::strong_ordering -{ - return lhs <=> static_cast(rhs); -} - -template -constexpr auto operator==(const VerifiedBasisType lhs, - const verified_type_basis rhs) -> bool -{ - return lhs == static_cast(rhs); -} - -template -constexpr auto operator<=>(const verified_type_basis lhs, - const OtherBasis rhs) -> std::strong_ordering -{ - return static_cast(lhs) <=> rhs; -} - -template -constexpr auto operator==(const verified_type_basis lhs, - const OtherBasis rhs) -> bool -{ - return static_cast(lhs) == rhs; -} - -template -constexpr auto operator<=>(const OtherBasis lhs, - const verified_type_basis rhs) -> std::strong_ordering -{ - return lhs <=> static_cast(rhs); -} - -template -constexpr auto operator==(const OtherBasis lhs, - const verified_type_basis rhs) -> bool -{ - return lhs == static_cast(rhs); -} - -} // namespace boost::safe_numbers::detail - -#endif // BOOST_SAFE_NUMBERS_VERIFIED_INTEGER_BASIS_HPP diff --git a/include/boost/safe_numbers/verified_integers.hpp b/include/boost/safe_numbers/verified_integers.hpp deleted file mode 100644 index 169db9b..0000000 --- a/include/boost/safe_numbers/verified_integers.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_SAFE_NUMBERS_VERIFIED_INTEGERS_HPP -#define BOOST_SAFE_NUMBERS_VERIFIED_INTEGERS_HPP - -#include -#include -#include - -namespace boost::safe_numbers { - -BOOST_SAFE_NUMBERS_EXPORT using verified_u8 = detail::verified_type_basis; - -BOOST_SAFE_NUMBERS_EXPORT using verified_u16 = detail::verified_type_basis; - -BOOST_SAFE_NUMBERS_EXPORT using verified_u32 = detail::verified_type_basis; - -BOOST_SAFE_NUMBERS_EXPORT using verified_u64 = detail::verified_type_basis; - -BOOST_SAFE_NUMBERS_EXPORT using verified_u128 = detail::verified_type_basis; - -BOOST_SAFE_NUMBERS_EXPORT template -using verified_bounded_integer = detail::verified_type_basis>; - -} // boost::safe_numbers - -#endif // BOOST_SAFE_NUMBERS_VERIFIED_INTEGERS_HPP From 8779eb9641b6879a82c883d74aa074dd8e7455c0 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 24 Feb 2026 10:08:28 -0500 Subject: [PATCH 2/5] Remove functional support for verified types --- include/boost/safe_numbers.hpp | 1 - include/boost/safe_numbers/bit.hpp | 64 ---------- .../boost/safe_numbers/byte_conversions.hpp | 119 ------------------ include/boost/safe_numbers/charconv.hpp | 15 --- .../boost/safe_numbers/detail/type_traits.hpp | 43 ------- .../boost/safe_numbers/integer_utilities.hpp | 79 ------------ include/boost/safe_numbers/iostream.hpp | 1 - include/boost/safe_numbers/limits.hpp | 47 ------- include/boost/safe_numbers/numeric.hpp | 52 -------- 9 files changed, 421 deletions(-) diff --git a/include/boost/safe_numbers.hpp b/include/boost/safe_numbers.hpp index 76d6f3c..5a0f0da 100644 --- a/include/boost/safe_numbers.hpp +++ b/include/boost/safe_numbers.hpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/safe_numbers/bit.hpp b/include/boost/safe_numbers/bit.hpp index 412f72b..77b7843 100644 --- a/include/boost/safe_numbers/bit.hpp +++ b/include/boost/safe_numbers/bit.hpp @@ -28,7 +28,6 @@ BOOST_SAFE_NUMBERS_EXPORT template } BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto bit_ceil(const UnsignedInt x) noexcept -> UnsignedInt { using boost::core::bit_ceil; @@ -38,17 +37,6 @@ BOOST_SAFE_NUMBERS_EXPORT template } BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto bit_ceil(const UnsignedInt x) noexcept -> UnsignedInt -{ - using boost::core::bit_ceil; - using underlying_type = detail::underlying_type_t; - - return UnsignedInt{bit_ceil(static_cast(x))}; -} - -BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto bit_floor(const UnsignedInt x) noexcept -> UnsignedInt { using boost::core::bit_floor; @@ -57,16 +45,6 @@ BOOST_SAFE_NUMBERS_EXPORT template return UnsignedInt{bit_floor(static_cast(x))}; } -BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto bit_floor(const UnsignedInt x) noexcept -> UnsignedInt -{ - using boost::core::bit_floor; - using underlying_type = detail::underlying_type_t; - - return UnsignedInt{bit_floor(static_cast(x))}; -} - BOOST_SAFE_NUMBERS_EXPORT template [[nodiscard]] constexpr auto bit_width(const UnsignedInt x) noexcept -> int { @@ -77,7 +55,6 @@ BOOST_SAFE_NUMBERS_EXPORT template } BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto rotl(const UnsignedInt x, const int s) noexcept -> UnsignedInt { using boost::core::rotl; @@ -87,17 +64,6 @@ BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto rotl(const UnsignedInt x, const int s) noexcept -> UnsignedInt -{ - using boost::core::rotl; - using underlying_type = detail::underlying_type_t; - - return UnsignedInt{rotl(static_cast(x), s)}; -} - -BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto rotr(const UnsignedInt x, const int s) noexcept -> UnsignedInt { using boost::core::rotr; @@ -106,16 +72,6 @@ BOOST_SAFE_NUMBERS_EXPORT template (x), s)}; } -BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto rotr(const UnsignedInt x, const int s) noexcept -> UnsignedInt -{ - using boost::core::rotr; - using underlying_type = detail::underlying_type_t; - - return UnsignedInt{rotr(static_cast(x), s)}; -} - BOOST_SAFE_NUMBERS_EXPORT template [[nodiscard]] constexpr auto countl_zero(const UnsignedInt x) noexcept -> int { @@ -162,7 +118,6 @@ BOOST_SAFE_NUMBERS_EXPORT template } BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto byteswap(const Int x) noexcept -> Int { using boost::core::byteswap; @@ -171,16 +126,6 @@ BOOST_SAFE_NUMBERS_EXPORT template (x))}; } -BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto byteswap(const Int x) noexcept -> Int -{ - using boost::core::byteswap; - using underlying_type = detail::underlying_type_t; - - return Int{byteswap(static_cast(x))}; -} - namespace detail { consteval auto reverse_byte(std::uint8_t b) noexcept -> std::uint8_t @@ -232,21 +177,12 @@ template } // namespace detail BOOST_SAFE_NUMBERS_EXPORT template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto bitswap(Int x) noexcept -> Int { using underlying_type = detail::underlying_type_t; return static_cast(detail::bitswap_impl(static_cast(x))); } -BOOST_SAFE_NUMBERS_EXPORT template - requires detail::is_verified_type_v -[[nodiscard]] consteval auto bitswap(const Int x) noexcept -> Int -{ - using underlying_type = detail::underlying_type_t; - return static_cast(detail::bitswap_impl(static_cast(x))); -} - } // namespace boost::safe_numbers #endif // BOOST_SAFE_NUMBERS_BIT_HPP diff --git a/include/boost/safe_numbers/byte_conversions.hpp b/include/boost/safe_numbers/byte_conversions.hpp index d8b55ff..52c95cf 100644 --- a/include/boost/safe_numbers/byte_conversions.hpp +++ b/include/boost/safe_numbers/byte_conversions.hpp @@ -6,7 +6,6 @@ #define BOOST_SAFE_NUMBERS_BYTE_CONVERSIONS_HPP #include -#include #include #ifndef BOOST_SAFE_NUMBERS_BUILD_MODULE @@ -21,7 +20,6 @@ namespace boost::safe_numbers { template - requires (!detail::is_verified_type_v) constexpr auto to_be(const T value) noexcept -> T { if constexpr (std::endian::native == std::endian::big) @@ -35,20 +33,6 @@ constexpr auto to_be(const T value) noexcept -> T } template -consteval auto to_be(const detail::verified_type_basis value) noexcept -> detail::verified_type_basis -{ - if constexpr (std::endian::native == std::endian::big) - { - return value; - } - else - { - return byteswap(value); - } -} - -template - requires (!detail::is_verified_type_v) constexpr auto from_be(const T value) noexcept -> T { // Self-inverse @@ -56,14 +40,6 @@ constexpr auto from_be(const T value) noexcept -> T } template -consteval auto from_be(const detail::verified_type_basis value) noexcept -> detail::verified_type_basis -{ - // Self-inverse - return to_be(value); -} - -template - requires (!detail::is_verified_type_v) constexpr auto to_le(const T value) noexcept -> T { if constexpr (std::endian::native == std::endian::little) @@ -77,20 +53,6 @@ constexpr auto to_le(const T value) noexcept -> T } template -consteval auto to_le(const detail::verified_type_basis value) noexcept -> detail::verified_type_basis -{ - if constexpr (std::endian::native == std::endian::little) - { - return value; - } - else - { - return byteswap(value); - } -} - -template - requires (!detail::is_verified_type_v) constexpr auto from_le(const T value) noexcept -> T { // Self-inverse @@ -98,29 +60,13 @@ constexpr auto from_le(const T value) noexcept -> T } template -consteval auto from_le(const detail::verified_type_basis value) noexcept -> detail::verified_type_basis -{ - // Self-inverse - return to_le(value); -} - -template - requires (!detail::is_verified_type_v) constexpr auto to_be_bytes(const T value) noexcept -> std::array { const auto be_value {to_be(value)}; return std::bit_cast>(be_value); } -template -consteval auto to_be_bytes(const detail::verified_type_basis value) noexcept -> std::array -{ - const auto be_value {to_be(value)}; - return std::bit_cast>(be_value); -} - template - requires (!detail::is_verified_type_v) constexpr auto from_be_bytes(const std::span bytes) -> T { using underlying_type = detail::underlying_type_t; @@ -155,37 +101,14 @@ constexpr auto from_be_bytes(const std::span bytes) -> T } } -template -consteval auto from_be_bytes(const std::span bytes) -> T -{ - using underlying_type = detail::underlying_type_t; - static_assert(N == sizeof(T), "The number of bytes provided, and the target type number of bytes do not match"); - - std::array arr {}; - for (std::size_t i {}; i < N; ++i) - { - arr[i] = bytes[i]; - } - return from_be(T{std::bit_cast(arr)}); -} - template - requires (!detail::is_verified_type_v) constexpr auto to_le_bytes(const T value) noexcept -> std::array { const auto le_value {to_le(value)}; return std::bit_cast>(le_value); } -template -consteval auto to_le_bytes(const detail::verified_type_basis value) noexcept -> std::array -{ - const auto le_value {to_le(value)}; - return std::bit_cast>(le_value); -} - template - requires (!detail::is_verified_type_v) constexpr auto from_le_bytes(const std::span bytes) -> T { using underlying_type = detail::underlying_type_t; @@ -220,22 +143,7 @@ constexpr auto from_le_bytes(const std::span bytes) -> T } } -template -consteval auto from_le_bytes(const std::span bytes) -> T -{ - using underlying_type = detail::underlying_type_t; - static_assert(N == sizeof(T), "The number of bytes provided, and the target type number of bytes do not match"); - - std::array arr {}; - for (std::size_t i {}; i < N; ++i) - { - arr[i] = bytes[i]; - } - return from_le(T{std::bit_cast(arr)}); -} - template - requires (!detail::is_verified_type_v) constexpr auto to_ne_bytes(const T value) noexcept -> std::array { if constexpr (std::endian::native == std::endian::little) @@ -248,21 +156,7 @@ constexpr auto to_ne_bytes(const T value) noexcept -> std::array -consteval auto to_ne_bytes(const detail::verified_type_basis value) noexcept -> std::array -{ - if constexpr (std::endian::native == std::endian::little) - { - return to_le_bytes(value); - } - else - { - return to_be_bytes(value); - } -} - template - requires (!detail::is_verified_type_v) constexpr auto from_ne_bytes(const std::span bytes) -> T { if constexpr (std::endian::native == std::endian::little) @@ -275,19 +169,6 @@ constexpr auto from_ne_bytes(const std::span bytes) -> T } } -template -consteval auto from_ne_bytes(const std::span bytes) -> T -{ - if constexpr (std::endian::native == std::endian::little) - { - return from_le_bytes(bytes); - } - else - { - return from_be_bytes(bytes); - } -} - } // namespace boost::safe_numbers #endif //BOOST_SAFE_NUMBERS_BYTE_CONVERSIONS_HPP diff --git a/include/boost/safe_numbers/charconv.hpp b/include/boost/safe_numbers/charconv.hpp index 4482e2c..c3c9564 100644 --- a/include/boost/safe_numbers/charconv.hpp +++ b/include/boost/safe_numbers/charconv.hpp @@ -17,7 +17,6 @@ namespace boost::charconv { template - requires (!safe_numbers::detail::is_verified_type_v) constexpr auto from_chars(const char* first, const char* last, T& value, int base = 10) -> charconv::from_chars_result { @@ -30,20 +29,6 @@ constexpr auto from_chars(const char* first, const char* last, T& value, int bas return r; } -template - requires safe_numbers::detail::is_verified_type_v -consteval auto from_chars(const char* first, const char* last, T& value, int base = 10) - -> charconv::from_chars_result -{ - using underlying_type = safe_numbers::detail::underlying_type_t; - - underlying_type result {}; - const auto r {charconv::from_chars(first, last, result, base)}; - value = T{result}; - - return r; -} - template constexpr auto to_chars(char* first, char* last, const T value, int base = 10) -> charconv::to_chars_result diff --git a/include/boost/safe_numbers/detail/type_traits.hpp b/include/boost/safe_numbers/detail/type_traits.hpp index 62275d6..0cba939 100644 --- a/include/boost/safe_numbers/detail/type_traits.hpp +++ b/include/boost/safe_numbers/detail/type_traits.hpp @@ -170,43 +170,6 @@ concept non_bounded_unsigned_library_type = is_unsigned_library_type_v && !is template concept non_bounded_integral_library_type = is_integral_library_type_v && !is_bounded_type_v; -// Forward declaration of verified_type_basis -template -class verified_type_basis; - -// is_verified_type trait - -namespace impl { - -template -struct is_verified_type : std::false_type {}; - -template -struct is_verified_type> : std::true_type {}; - -template -struct is_library_type> : std::true_type {}; - -template - requires is_unsigned_library_type_v -struct is_unsigned_library_type> : std::true_type {}; - -template - requires is_bounded_type_v -struct is_bounded_type> : std::true_type {}; - -template - requires is_integral_library_type_v -struct is_integral_library_type> : std::true_type {}; - -} // namespace impl - -template -inline constexpr bool is_verified_type_v = impl::is_verified_type::value; - -template -concept verified_type = is_verified_type_v; - // underlying specialization for bounded_uint namespace impl { @@ -217,12 +180,6 @@ struct underlying> using type = typename underlying::basis_type>::type; }; -template -struct underlying> -{ - using type = typename underlying::type; -}; - } // namespace impl // Promotes an unsigned integer to the next higher type diff --git a/include/boost/safe_numbers/integer_utilities.hpp b/include/boost/safe_numbers/integer_utilities.hpp index f40395e..a66f0aa 100644 --- a/include/boost/safe_numbers/integer_utilities.hpp +++ b/include/boost/safe_numbers/integer_utilities.hpp @@ -15,7 +15,6 @@ namespace boost::safe_numbers { // Newton's method as it can't possibly overflow, and converges rapidly template - requires (!detail::is_verified_type_v) constexpr auto isqrt(const T val) -> T { using underlying = typename detail::underlying_type_t; @@ -43,13 +42,6 @@ constexpr auto isqrt(const T val) -> T } template -consteval auto isqrt(const detail::verified_type_basis val) -> detail::verified_type_basis -{ - return detail::verified_type_basis{isqrt(static_cast(val))}; -} - -template - requires (!detail::is_verified_type_v) constexpr auto remove_trailing_zeros(const T n) { using underlying = typename detail::underlying_type_t; @@ -63,20 +55,6 @@ constexpr auto remove_trailing_zeros(const T n) } template -consteval auto remove_trailing_zeros(const detail::verified_type_basis val) -{ - using underlying = typename detail::underlying_type_t; - - if (static_cast(val) == static_cast(0)) - { - return detail::remove_trailing_zeros_return{static_cast(0), static_cast(0)}; - } - - return detail::remove_trailing_zeros(static_cast(val)); -} - -template - requires (!detail::is_verified_type_v) constexpr auto is_power_10(const T n) -> bool { using underlying = typename detail::underlying_type_t; @@ -86,58 +64,27 @@ constexpr auto is_power_10(const T n) -> bool } template -consteval auto is_power_10(const detail::verified_type_basis n) -> bool -{ - using underlying = typename detail::underlying_type_t; - - const auto [trimmed_number, _] = detail::remove_trailing_zeros(static_cast(n)); - return trimmed_number == static_cast(1); -} - -template - requires (!detail::is_verified_type_v) constexpr auto is_power_2(const T n) noexcept -> bool { return has_single_bit(n); } -template -consteval auto is_power_2(const detail::verified_type_basis n) noexcept -> bool -{ - return has_single_bit(n); -} - // Integer log base 2: floor(log2(n)) == bit_width(n) - 1 template - requires (!detail::is_verified_type_v) constexpr auto log2(const T n) noexcept -> int { return bit_width(n) - 1; } -template -consteval auto log2(const detail::verified_type_basis n) noexcept -> int -{ - return bit_width(n) - 1; -} - // Integer log base 10: floor(log10(n)) == num_digits(n) - 1 // Uses MSB-based approximation with power-of-10 table lookup (O(1)) template - requires (!detail::is_verified_type_v) constexpr auto log10(const T n) noexcept -> int { using underlying = detail::underlying_type_t; return detail::num_digits(static_cast(n)) - 1; } -template -consteval auto log10(const detail::verified_type_basis n) noexcept -> int -{ - using underlying = detail::underlying_type_t; - return detail::num_digits(static_cast(n)) - 1; -} - namespace detail { // Iterative exponentiation by squaring: O(log b) multiplications @@ -167,37 +114,18 @@ constexpr auto ipow_impl(T base, T exp) -> T } // namespace detail template - requires (!detail::is_verified_type_v) constexpr auto ipow(const T a, const T b) -> T { return detail::ipow_impl(a, b); } -template -consteval auto ipow(const detail::verified_type_basis a, - const detail::verified_type_basis b) -> detail::verified_type_basis -{ - // This is a workaround for P2564R3 "Consteval should propagate up" - // Operate on the underlying type rather than on the verfied type directly - return detail::verified_type_basis{detail::ipow_impl(static_cast(a), static_cast(b))}; -} - template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto abs_diff(const T a, const T b) noexcept -> T { return a > b ? a - b : b - a; } template -[[nodiscard]] consteval auto abs_diff(const detail::verified_type_basis a, - const detail::verified_type_basis b) noexcept -> detail::verified_type_basis -{ - return detail::verified_type_basis{abs_diff(static_cast(a), static_cast(b))}; -} - -template - requires (!detail::is_verified_type_v) [[nodiscard]] constexpr auto div_ceil(const T a, const T b) noexcept -> T { using underlying = detail::underlying_type_t; @@ -215,13 +143,6 @@ template } } -template -[[nodiscard]] consteval auto div_ceil(const detail::verified_type_basis a, - const detail::verified_type_basis b) noexcept -> detail::verified_type_basis -{ - return detail::verified_type_basis{div_ceil(static_cast(a), static_cast(b))}; -} - } // namespace boost::safe_numbers #endif // BOOST_SAFE_NUMBERS_INTEGER_UTILITIES_HPP diff --git a/include/boost/safe_numbers/iostream.hpp b/include/boost/safe_numbers/iostream.hpp index 330c846..dd7f8e3 100644 --- a/include/boost/safe_numbers/iostream.hpp +++ b/include/boost/safe_numbers/iostream.hpp @@ -25,7 +25,6 @@ namespace boost::safe_numbers::detail { #endif BOOST_SAFE_NUMBERS_EXPORT template - requires (!is_verified_type_v) auto operator>>(std::basic_istream& is, LibType& v) -> std::basic_istream& { using underlying_type = underlying_type_t; diff --git a/include/boost/safe_numbers/limits.hpp b/include/boost/safe_numbers/limits.hpp index db7c085..5711fc3 100644 --- a/include/boost/safe_numbers/limits.hpp +++ b/include/boost/safe_numbers/limits.hpp @@ -8,7 +8,6 @@ #include #include #include -#include #ifndef BOOST_SAFE_NUMBERS_BUILD_MODULE @@ -137,52 +136,6 @@ class numeric_limits> static constexpr type denorm_min() { return min(); } }; -template -class numeric_limits> -{ - using type = boost::safe_numbers::detail::verified_type_basis; - using basis_limits = std::numeric_limits; - -public: - static constexpr bool is_specialized = basis_limits::is_specialized; - static constexpr bool is_signed = basis_limits::is_signed; - static constexpr bool is_integer = basis_limits::is_integer; - static constexpr bool is_exact = basis_limits::is_exact; - static constexpr bool has_infinity = basis_limits::has_infinity; - static constexpr bool has_quiet_NaN = basis_limits::has_quiet_NaN; - static constexpr bool has_signaling_NaN = basis_limits::has_signaling_NaN; - - #if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L))) - static constexpr std::float_denorm_style has_denorm = basis_limits::has_denorm; - static constexpr bool has_denorm_loss = basis_limits::has_denorm_loss; - #endif - - static constexpr std::float_round_style round_style = basis_limits::round_style; - static constexpr bool is_iec559 = basis_limits::is_iec559; - static constexpr bool is_bounded = basis_limits::is_bounded; - static constexpr bool is_modulo = basis_limits::is_modulo; - static constexpr int digits = basis_limits::digits; - static constexpr int digits10 = basis_limits::digits10; - static constexpr int max_digits10 = basis_limits::max_digits10; - static constexpr int radix = basis_limits::radix; - static constexpr int min_exponent = basis_limits::min_exponent; - static constexpr int min_exponent10 = basis_limits::min_exponent10; - static constexpr int max_exponent = basis_limits::max_exponent; - static constexpr int max_exponent10 = basis_limits::max_exponent10; - static constexpr bool traps = basis_limits::traps; - static constexpr bool tinyness_before = basis_limits::tinyness_before; - - static constexpr type min() { return type{basis_limits::min()}; } - static constexpr type max() { return type{basis_limits::max()}; } - static constexpr type lowest() { return type{basis_limits::lowest()}; } - static constexpr type epsilon() { return type{basis_limits::epsilon()}; } - static constexpr type round_error() { return type{basis_limits::round_error()}; } - static constexpr type infinity() { return type{basis_limits::infinity()}; } - static constexpr type quiet_NaN() { return type{basis_limits::quiet_NaN()}; } - static constexpr type signaling_NaN() { return type{basis_limits::signaling_NaN()}; } - static constexpr type denorm_min() { return type{basis_limits::denorm_min()}; } -}; - #ifdef __clang__ # pragma clang diagnostic pop #endif diff --git a/include/boost/safe_numbers/numeric.hpp b/include/boost/safe_numbers/numeric.hpp index 2aaecf8..17eed4e 100644 --- a/include/boost/safe_numbers/numeric.hpp +++ b/include/boost/safe_numbers/numeric.hpp @@ -5,7 +5,6 @@ #ifndef BOOST_SAFE_NUMBERS_NUMERIC_HPP #define BOOST_SAFE_NUMBERS_NUMERIC_HPP -#include #include #include @@ -18,7 +17,6 @@ namespace boost::safe_numbers { template - requires (!detail::is_verified_type_v) constexpr auto gcd(const T m, const T n) noexcept -> T { using underlying_type = detail::underlying_type_t; @@ -34,23 +32,6 @@ constexpr auto gcd(const T m, const T n) noexcept -> T } template -consteval auto gcd(const detail::verified_type_basis m, const detail::verified_type_basis n) noexcept -> detail::verified_type_basis -{ - using underlying_type = detail::underlying_type_t; - using return_type = detail::verified_type_basis; - - if constexpr (std::is_same_v || std::is_same_v) - { - return return_type{T{int128::gcd(static_cast(m), static_cast(n))}}; - } - else - { - return return_type{T{static_cast(std::gcd(static_cast(m), static_cast(n)))}}; - } -} - -template - requires (!detail::is_verified_type_v) constexpr auto lcm(const T m, const T n) noexcept -> T { using underlying_type = detail::underlying_type_t; @@ -66,23 +47,6 @@ constexpr auto lcm(const T m, const T n) noexcept -> T } template -consteval auto lcm(const detail::verified_type_basis m, const detail::verified_type_basis n) noexcept -> detail::verified_type_basis -{ - using underlying_type = detail::underlying_type_t; - using return_type = detail::verified_type_basis; - - if constexpr (std::is_same_v || std::is_same_v) - { - return return_type{T{int128::lcm(static_cast(m), static_cast(n))}}; - } - else - { - return return_type{T{static_cast(std::lcm(static_cast(m), static_cast(n)))}}; - } -} - -template - requires (!detail::is_verified_type_v) constexpr auto midpoint(const T a, const T b) noexcept -> T { using underlying_type = detail::underlying_type_t; @@ -97,22 +61,6 @@ constexpr auto midpoint(const T a, const T b) noexcept -> T } } -template -consteval auto midpoint(const detail::verified_type_basis a, const detail::verified_type_basis b) noexcept -> detail::verified_type_basis -{ - using underlying_type = detail::underlying_type_t; - using return_type = detail::verified_type_basis; - - if constexpr (std::is_same_v || std::is_same_v) - { - return return_type{T{int128::midpoint(static_cast(a), static_cast(b))}}; - } - else - { - return return_type{T{static_cast(std::midpoint(static_cast(a), static_cast(b)))}}; - } -} - } // namespace boost::safe_numbers #endif // BOOST_SAFE_NUMBERS_NUMERIC_HPP From ed8418ee6d04f5fb62eda6fbf939d938bf185c22 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 24 Feb 2026 10:08:51 -0500 Subject: [PATCH 3/5] Remove testing of verified types --- test/Jamfile | 17 - test/compile_fail_verified_cross_type_add.cpp | 19 - ...le_fail_verified_cross_type_comparison.cpp | 19 - .../compile_fail_verified_mixed_width_add.cpp | 18 - test/test_abs_diff.cpp | 37 -- test/test_div_ceil.cpp | 37 -- test/test_gcd.cpp | 37 -- test/test_ipow.cpp | 28 - test/test_is_power_10.cpp | 34 -- test/test_is_power_2.cpp | 34 -- test/test_isqrt.cpp | 43 -- test/test_lcm.cpp | 37 -- test/test_log10.cpp | 24 - test/test_log2.cpp | 24 - test/test_midpoint.cpp | 37 -- test/test_remove_trailing_zeros.cpp | 43 -- test/test_to_from_be.cpp | 50 +- test/test_to_from_be_bytes.cpp | 79 +-- test/test_to_from_le.cpp | 49 +- test/test_to_from_le_bytes.cpp | 79 +-- test/test_to_from_ne_bytes.cpp | 40 +- test/test_verified_bit.cpp | 303 --------- test/test_verified_charconv.cpp | 199 ------ test/test_verified_fmt_format.cpp | 91 --- test/test_verified_integers.cpp | 365 ----------- test/test_verified_limits.cpp | 175 ------ test/test_verified_mixed_ops.cpp | 573 ------------------ test/test_verified_std_format.cpp | 92 --- test/test_verified_streaming.cpp | 77 --- 29 files changed, 5 insertions(+), 2655 deletions(-) delete mode 100644 test/compile_fail_verified_cross_type_add.cpp delete mode 100644 test/compile_fail_verified_cross_type_comparison.cpp delete mode 100644 test/compile_fail_verified_mixed_width_add.cpp delete mode 100644 test/test_verified_bit.cpp delete mode 100644 test/test_verified_charconv.cpp delete mode 100644 test/test_verified_fmt_format.cpp delete mode 100644 test/test_verified_integers.cpp delete mode 100644 test/test_verified_limits.cpp delete mode 100644 test/test_verified_mixed_ops.cpp delete mode 100644 test/test_verified_std_format.cpp delete mode 100644 test/test_verified_streaming.cpp diff --git a/test/Jamfile b/test/Jamfile index 2e3fc66..97cadbe 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -112,18 +112,6 @@ run test_unsigned_bounded_std_format.cpp ; compile-fail compile_fail_bounded_mixed_ops.cpp ; compile-fail compile_fail_bounded_bool_bounds.cpp ; -run test_verified_integers.cpp ; -run test_verified_mixed_ops.cpp ; -compile-fail compile_fail_verified_mixed_width_add.cpp ; -compile-fail compile_fail_verified_cross_type_add.cpp ; -compile-fail compile_fail_verified_cross_type_comparison.cpp ; -run test_verified_streaming.cpp ; -run test_verified_bit.cpp ; -run test_verified_charconv.cpp ; -run test_verified_fmt_format.cpp ; -run test_verified_std_format.cpp ; -run test_verified_limits.cpp ; - # Byte conversion tests run test_to_from_be.cpp ; run test_to_from_le.cpp ; @@ -173,11 +161,6 @@ run ../examples/charconv.cpp ; run ../examples/bit.cpp ; run ../examples/bounded_limits.cpp ; run ../examples/bitwise_ops.cpp ; -run ../examples/verified_construction.cpp ; -run ../examples/verified_arithmetic.cpp ; -run ../examples/verified_runtime_usage.cpp ; -run ../examples/verified_mixed_ops.cpp ; -compile-fail ../examples/compile_fail_verified_overflow.cpp ; run ../examples/safe_numerics_comparison.cpp ; run ../examples/byte_conversions.cpp ; run ../examples/std_numeric_usage.cpp ; diff --git a/test/compile_fail_verified_cross_type_add.cpp b/test/compile_fail_verified_cross_type_add.cpp deleted file mode 100644 index a37e384..0000000 --- a/test/compile_fail_verified_cross_type_add.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include - -using namespace boost::safe_numbers; - -int main() -{ - constexpr auto a = verified_u32{u32{10}}; - constexpr auto b = verified_u64{u64{20}}; - - // This should fail to compile: can not perform addition between - // verified types with different basis types - auto c = a + b; - - return 0; -} diff --git a/test/compile_fail_verified_cross_type_comparison.cpp b/test/compile_fail_verified_cross_type_comparison.cpp deleted file mode 100644 index 17d05d4..0000000 --- a/test/compile_fail_verified_cross_type_comparison.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include - -using namespace boost::safe_numbers; - -int main() -{ - constexpr auto a = verified_u32{u32{10}}; - constexpr auto b = verified_u64{u64{10}}; - - // This should fail to compile: can not compare verified types - // with different basis types - auto result = (a == b); - - return 0; -} diff --git a/test/compile_fail_verified_mixed_width_add.cpp b/test/compile_fail_verified_mixed_width_add.cpp deleted file mode 100644 index 2b18b61..0000000 --- a/test/compile_fail_verified_mixed_width_add.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include - -using namespace boost::safe_numbers; - -int main() -{ - constexpr auto a = verified_u32{u32{10}}; - const auto b = u64{20}; - - // This should fail to compile: verified_u32 + u64 is a mixed-width operation - auto c = a + b; - - return 0; -} diff --git a/test/test_abs_diff.cpp b/test/test_abs_diff.cpp index c89ee88..e5974e5 100644 --- a/test/test_abs_diff.cpp +++ b/test/test_abs_diff.cpp @@ -204,40 +204,6 @@ void test_abs_diff_constexpr() static_assert(abs_diff(u64{UINT64_C(1000)}, u64{UINT64_C(3000)}) == u64{UINT64_C(2000)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_abs_diff_verified() -{ - // verified_u8 - static_assert(abs_diff(verified_u8{u8{static_cast(10)}}, - verified_u8{u8{static_cast(3)}}) == verified_u8{u8{static_cast(7)}}); - static_assert(abs_diff(verified_u8{u8{static_cast(3)}}, - verified_u8{u8{static_cast(10)}}) == verified_u8{u8{static_cast(7)}}); - static_assert(abs_diff(verified_u8{u8{static_cast(0)}}, - verified_u8{u8{static_cast(0)}}) == verified_u8{u8{static_cast(0)}}); - - // verified_u16 - static_assert(abs_diff(verified_u16{u16{static_cast(1000)}}, - verified_u16{u16{static_cast(3000)}}) == verified_u16{u16{static_cast(2000)}}); - - // verified_u32 - static_assert(abs_diff(verified_u32{u32{UINT32_C(100)}}, - verified_u32{u32{UINT32_C(200)}}) == verified_u32{u32{UINT32_C(100)}}); - - // verified_u64 - static_assert(abs_diff(verified_u64{u64{UINT64_C(1000)}}, - verified_u64{u64{UINT64_C(3000)}}) == verified_u64{u64{UINT64_C(2000)}}); - - // verified_u128 - using boost::int128::uint128_t; - static_assert(abs_diff(verified_u128{u128{uint128_t{10}}}, - verified_u128{u128{uint128_t{3}}}) == verified_u128{u128{uint128_t{7}}}); - static_assert(abs_diff(verified_u128{u128{uint128_t{3}}}, - verified_u128{u128{uint128_t{10}}}) == verified_u128{u128{uint128_t{7}}}); -} - int main() { // Equal values - all types @@ -283,8 +249,5 @@ int main() // Constexpr evaluation test_abs_diff_constexpr(); - // Verified types (consteval) - test_abs_diff_verified(); - return boost::report_errors(); } diff --git a/test/test_div_ceil.cpp b/test/test_div_ceil.cpp index 7daa25e..e2112d1 100644 --- a/test/test_div_ceil.cpp +++ b/test/test_div_ceil.cpp @@ -212,40 +212,6 @@ void test_div_ceil_constexpr() static_assert(div_ceil(u64{UINT64_C(1000)}, u64{UINT64_C(3)}) == u64{UINT64_C(334)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_div_ceil_verified() -{ - // verified_u8 - static_assert(div_ceil(verified_u8{u8{static_cast(10)}}, - verified_u8{u8{static_cast(3)}}) == verified_u8{u8{static_cast(4)}}); - static_assert(div_ceil(verified_u8{u8{static_cast(9)}}, - verified_u8{u8{static_cast(3)}}) == verified_u8{u8{static_cast(3)}}); - static_assert(div_ceil(verified_u8{u8{static_cast(0)}}, - verified_u8{u8{static_cast(1)}}) == verified_u8{u8{static_cast(0)}}); - - // verified_u16 - static_assert(div_ceil(verified_u16{u16{static_cast(1000)}}, - verified_u16{u16{static_cast(3)}}) == verified_u16{u16{static_cast(334)}}); - - // verified_u32 - static_assert(div_ceil(verified_u32{u32{UINT32_C(100)}}, - verified_u32{u32{UINT32_C(7)}}) == verified_u32{u32{UINT32_C(15)}}); - - // verified_u64 - static_assert(div_ceil(verified_u64{u64{UINT64_C(1000)}}, - verified_u64{u64{UINT64_C(3)}}) == verified_u64{u64{UINT64_C(334)}}); - - // verified_u128 - using boost::int128::uint128_t; - static_assert(div_ceil(verified_u128{u128{uint128_t{10}}}, - verified_u128{u128{uint128_t{3}}}) == verified_u128{u128{uint128_t{4}}}); - static_assert(div_ceil(verified_u128{u128{uint128_t{9}}}, - verified_u128{u128{uint128_t{3}}}) == verified_u128{u128{uint128_t{3}}}); -} - int main() { // Division by one - all types @@ -291,8 +257,5 @@ int main() // Constexpr evaluation test_div_ceil_constexpr(); - // Verified types (consteval) - test_div_ceil_verified(); - return boost::report_errors(); } diff --git a/test/test_gcd.cpp b/test/test_gcd.cpp index cf96525..1d5331f 100644 --- a/test/test_gcd.cpp +++ b/test/test_gcd.cpp @@ -220,40 +220,6 @@ void test_gcd_constexpr() static_assert(gcd(u64{UINT64_C(1346269)}, u64{UINT64_C(832040)}) == u64{UINT64_C(1)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_gcd_verified() -{ - // verified_u8 - static_assert(gcd(verified_u8{u8{static_cast(12)}}, - verified_u8{u8{static_cast(8)}}) == verified_u8{u8{static_cast(4)}}); - static_assert(gcd(verified_u8{u8{static_cast(0)}}, - verified_u8{u8{static_cast(5)}}) == verified_u8{u8{static_cast(5)}}); - static_assert(gcd(verified_u8{u8{static_cast(7)}}, - verified_u8{u8{static_cast(11)}}) == verified_u8{u8{static_cast(1)}}); - - // verified_u16 - static_assert(gcd(verified_u16{u16{static_cast(1000)}}, - verified_u16{u16{static_cast(750)}}) == verified_u16{u16{static_cast(250)}}); - - // verified_u32 - static_assert(gcd(verified_u32{u32{UINT32_C(1234567890)}}, - verified_u32{u32{UINT32_C(987654321)}}) == verified_u32{u32{UINT32_C(9)}}); - - // verified_u64 - static_assert(gcd(verified_u64{u64{UINT64_C(1000000000000)}}, - verified_u64{u64{UINT64_C(750000000000)}}) == verified_u64{u64{UINT64_C(250000000000)}}); - - // verified_u128 - using boost::int128::uint128_t; - static_assert(gcd(verified_u128{u128{uint128_t{12}}}, - verified_u128{u128{uint128_t{8}}}) == verified_u128{u128{uint128_t{4}}}); - static_assert(gcd(verified_u128{u128{uint128_t{100}}}, - verified_u128{u128{uint128_t{75}}}) == verified_u128{u128{uint128_t{25}}}); -} - int main() { // Zero cases - all types @@ -296,8 +262,5 @@ int main() // Constexpr evaluation test_gcd_constexpr(); - // Verified types (consteval) - test_gcd_verified(); - return boost::report_errors(); } diff --git a/test/test_ipow.cpp b/test/test_ipow.cpp index 99fafda..1d3e003 100644 --- a/test/test_ipow.cpp +++ b/test/test_ipow.cpp @@ -268,31 +268,6 @@ void test_ipow_constexpr() static_assert(ipow(u64{UINT64_C(10)}, u64{UINT64_C(18)}) == u64{UINT64_C(1000000000000000000)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_ipow_verified() -{ - static_assert(ipow(verified_u8{u8{static_cast(2)}}, - verified_u8{u8{static_cast(7)}}) == verified_u8{u8{static_cast(128)}}); - static_assert(ipow(verified_u8{u8{static_cast(5)}}, - verified_u8{u8{static_cast(3)}}) == verified_u8{u8{static_cast(125)}}); - - static_assert(ipow(verified_u16{u16{static_cast(10)}}, - verified_u16{u16{static_cast(4)}}) == verified_u16{u16{static_cast(10000)}}); - - static_assert(ipow(verified_u32{u32{UINT32_C(10)}}, - verified_u32{u32{UINT32_C(9)}}) == verified_u32{u32{UINT32_C(1000000000)}}); - - static_assert(ipow(verified_u64{u64{UINT64_C(2)}}, - verified_u64{u64{UINT64_C(40)}}) == verified_u64{u64{UINT64_C(1099511627776)}}); - - using boost::int128::uint128_t; - static_assert(ipow(verified_u128{u128{uint128_t{2}}}, - verified_u128{u128{uint128_t{10}}}) == verified_u128{u128{uint128_t{1024}}}); -} - int main() { // Base cases - all types @@ -339,8 +314,5 @@ int main() // Constexpr evaluation test_ipow_constexpr(); - // Verified types (consteval) - test_ipow_verified(); - return boost::report_errors(); } diff --git a/test/test_is_power_10.cpp b/test/test_is_power_10.cpp index ff46a53..d07ca36 100644 --- a/test/test_is_power_10.cpp +++ b/test/test_is_power_10.cpp @@ -175,30 +175,6 @@ void test_is_power_10_constexpr() static_assert(!is_power_10(u64{UINT64_C(7)})); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_is_power_10_verified() -{ - static_assert(is_power_10(verified_u8{u8{static_cast(1)}})); - static_assert(is_power_10(verified_u8{u8{static_cast(10)}})); - static_assert(!is_power_10(verified_u8{u8{static_cast(5)}})); - - static_assert(is_power_10(verified_u16{u16{static_cast(1000)}})); - static_assert(!is_power_10(verified_u16{u16{static_cast(999)}})); - - static_assert(is_power_10(verified_u32{u32{UINT32_C(100)}})); - static_assert(!is_power_10(verified_u32{u32{UINT32_C(200)}})); - - static_assert(is_power_10(verified_u64{u64{UINT64_C(1000000)}})); - static_assert(!is_power_10(verified_u64{u64{UINT64_C(999999)}})); - - using boost::int128::uint128_t; - static_assert(is_power_10(verified_u128{u128{uint128_t{UINT64_C(100000)}}})); - static_assert(!is_power_10(verified_u128{u128{uint128_t{UINT64_C(100001)}}})); -} - // ============================================================================= // Zero input tests // ============================================================================= @@ -217,12 +193,6 @@ void test_is_power_10_zero_constexpr() static_assert(!is_power_10(u64{UINT64_C(0)})); } -void test_is_power_10_zero_verified() -{ - static_assert(!is_power_10(verified_u8{u8{static_cast(0)}})); - static_assert(!is_power_10(verified_u32{u32{UINT32_C(0)}})); -} - int main() { // Zero input - all types @@ -232,7 +202,6 @@ int main() test_is_power_10_zero(); test_is_power_10_zero(); test_is_power_10_zero_constexpr(); - test_is_power_10_zero_verified(); // Powers of 10 - all types test_is_power_10_true(); @@ -262,8 +231,5 @@ int main() // Constexpr evaluation test_is_power_10_constexpr(); - // Verified types (consteval) - test_is_power_10_verified(); - return boost::report_errors(); } diff --git a/test/test_is_power_2.cpp b/test/test_is_power_2.cpp index 227cc19..ae0b50a 100644 --- a/test/test_is_power_2.cpp +++ b/test/test_is_power_2.cpp @@ -186,30 +186,6 @@ void test_is_power_2_constexpr() static_assert(!is_power_2(u64{UINT64_C(9223372036854775807)})); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_is_power_2_verified() -{ - static_assert(is_power_2(verified_u8{u8{static_cast(1)}})); - static_assert(is_power_2(verified_u8{u8{static_cast(64)}})); - static_assert(!is_power_2(verified_u8{u8{static_cast(5)}})); - - static_assert(is_power_2(verified_u16{u16{static_cast(4096)}})); - static_assert(!is_power_2(verified_u16{u16{static_cast(4095)}})); - - static_assert(is_power_2(verified_u32{u32{UINT32_C(1048576)}})); - static_assert(!is_power_2(verified_u32{u32{UINT32_C(1000000)}})); - - static_assert(is_power_2(verified_u64{u64{UINT64_C(4294967296)}})); - static_assert(!is_power_2(verified_u64{u64{UINT64_C(4294967295)}})); - - using boost::int128::uint128_t; - static_assert(is_power_2(verified_u128{u128{uint128_t{UINT64_C(1099511627776)}}})); - static_assert(!is_power_2(verified_u128{u128{uint128_t{UINT64_C(1099511627775)}}})); -} - // ============================================================================= // Zero input tests // ============================================================================= @@ -228,12 +204,6 @@ void test_is_power_2_zero_constexpr() static_assert(!is_power_2(u64{UINT64_C(0)})); } -void test_is_power_2_zero_verified() -{ - static_assert(!is_power_2(verified_u8{u8{static_cast(0)}})); - static_assert(!is_power_2(verified_u32{u32{UINT32_C(0)}})); -} - int main() { // Zero input - all types @@ -243,7 +213,6 @@ int main() test_is_power_2_zero(); test_is_power_2_zero(); test_is_power_2_zero_constexpr(); - test_is_power_2_zero_verified(); // Powers of 2 - all types test_is_power_2_true(); @@ -273,8 +242,5 @@ int main() // Constexpr evaluation test_is_power_2_constexpr(); - // Verified types (consteval) - test_is_power_2_verified(); - return boost::report_errors(); } diff --git a/test/test_isqrt.cpp b/test/test_isqrt.cpp index 2e74009..64348a7 100644 --- a/test/test_isqrt.cpp +++ b/test/test_isqrt.cpp @@ -138,46 +138,6 @@ void test_isqrt_constexpr() BOOST_TEST_EQ(r10, u32{3}); } -// ============================================================================= -// Verified type isqrt tests (consteval) -// ============================================================================= - -void test_isqrt_verified() -{ - constexpr auto r0 = isqrt(verified_u8{u8{0}}); - constexpr auto r1 = isqrt(verified_u8{u8{1}}); - constexpr auto r4 = isqrt(verified_u8{u8{4}}); - constexpr auto r9 = isqrt(verified_u8{u8{9}}); - - BOOST_TEST_EQ(r0, verified_u8{u8{0}}); - BOOST_TEST_EQ(r1, verified_u8{u8{1}}); - BOOST_TEST_EQ(r4, verified_u8{u8{2}}); - BOOST_TEST_EQ(r9, verified_u8{u8{3}}); - - constexpr auto r16 = isqrt(verified_u16{u16{16}}); - constexpr auto r25 = isqrt(verified_u16{u16{25}}); - constexpr auto r10 = isqrt(verified_u16{u16{10}}); - - BOOST_TEST_EQ(r16, verified_u16{u16{4}}); - BOOST_TEST_EQ(r25, verified_u16{u16{5}}); - BOOST_TEST_EQ(r10, verified_u16{u16{3}}); - - constexpr auto r100 = isqrt(verified_u32{u32{100}}); - constexpr auto r144 = isqrt(verified_u32{u32{144}}); - constexpr auto r200 = isqrt(verified_u32{u32{200}}); - - BOOST_TEST_EQ(r100, verified_u32{u32{10}}); - BOOST_TEST_EQ(r144, verified_u32{u32{12}}); - BOOST_TEST_EQ(r200, verified_u32{u32{14}}); - - constexpr auto r64_val = isqrt(verified_u64{u64{1000000}}); - BOOST_TEST_EQ(r64_val, verified_u64{u64{1000}}); - - using boost::int128::uint128_t; - constexpr auto r128_val = isqrt(verified_u128{u128{uint128_t{10000}}}); - BOOST_TEST_EQ(r128_val, verified_u128{u128{uint128_t{100}}}); -} - // ============================================================================= // Verify isqrt result property: result^2 <= n < (result+1)^2 // ============================================================================= @@ -231,9 +191,6 @@ int main() // Constexpr evaluation test_isqrt_constexpr(); - // Verified types (consteval) - test_isqrt_verified(); - // Property: r^2 <= n < (r+1)^2 for all values 0..255 test_isqrt_property(); test_isqrt_property(); diff --git a/test/test_lcm.cpp b/test/test_lcm.cpp index 1064930..b265e49 100644 --- a/test/test_lcm.cpp +++ b/test/test_lcm.cpp @@ -255,40 +255,6 @@ void test_lcm_constexpr() static_assert(lcm(u64{UINT64_C(7)}, u64{UINT64_C(11)}) == u64{UINT64_C(77)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_lcm_verified() -{ - // verified_u8 - static_assert(lcm(verified_u8{u8{static_cast(4)}}, - verified_u8{u8{static_cast(6)}}) == verified_u8{u8{static_cast(12)}}); - static_assert(lcm(verified_u8{u8{static_cast(0)}}, - verified_u8{u8{static_cast(5)}}) == verified_u8{u8{static_cast(0)}}); - static_assert(lcm(verified_u8{u8{static_cast(7)}}, - verified_u8{u8{static_cast(11)}}) == verified_u8{u8{static_cast(77)}}); - - // verified_u16 - static_assert(lcm(verified_u16{u16{static_cast(100)}}, - verified_u16{u16{static_cast(75)}}) == verified_u16{u16{static_cast(300)}}); - - // verified_u32 - static_assert(lcm(verified_u32{u32{UINT32_C(12)}}, - verified_u32{u32{UINT32_C(18)}}) == verified_u32{u32{UINT32_C(36)}}); - - // verified_u64 - static_assert(lcm(verified_u64{u64{UINT64_C(1000000)}}, - verified_u64{u64{UINT64_C(750000)}}) == verified_u64{u64{UINT64_C(3000000)}}); - - // verified_u128 - using boost::int128::uint128_t; - static_assert(lcm(verified_u128{u128{uint128_t{4}}}, - verified_u128{u128{uint128_t{6}}}) == verified_u128{u128{uint128_t{12}}}); - static_assert(lcm(verified_u128{u128{uint128_t{7}}}, - verified_u128{u128{uint128_t{11}}}) == verified_u128{u128{uint128_t{77}}}); -} - int main() { // Zero cases - all types @@ -338,8 +304,5 @@ int main() // Constexpr evaluation test_lcm_constexpr(); - // Verified types (consteval) - test_lcm_verified(); - return boost::report_errors(); } diff --git a/test/test_log10.cpp b/test/test_log10.cpp index 32652b0..c06e1d0 100644 --- a/test/test_log10.cpp +++ b/test/test_log10.cpp @@ -217,27 +217,6 @@ void test_log10_constexpr() static_assert(log10(u64{UINT64_C(10000000000000000000)}) == 19); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_log10_verified() -{ - static_assert(log10(verified_u8{u8{static_cast(1)}}) == 0); - static_assert(log10(verified_u8{u8{static_cast(10)}}) == 1); - static_assert(log10(verified_u8{u8{static_cast(100)}}) == 2); - - static_assert(log10(verified_u16{u16{static_cast(10000)}}) == 4); - - static_assert(log10(verified_u32{u32{UINT32_C(1000000000)}}) == 9); - static_assert(log10(verified_u32{u32{UINT32_C(4294967295)}}) == 9); - - static_assert(log10(verified_u64{u64{UINT64_C(10000000000000000000)}}) == 19); - - using boost::int128::uint128_t; - static_assert(log10(verified_u128{u128{uint128_t{UINT64_C(1000000000000)}}}) == 12); -} - int main() { // Powers of 10 - all types @@ -277,8 +256,5 @@ int main() // Constexpr evaluation test_log10_constexpr(); - // Verified types (consteval) - test_log10_verified(); - return boost::report_errors(); } diff --git a/test/test_log2.cpp b/test/test_log2.cpp index f4fe41a..8a7df47 100644 --- a/test/test_log2.cpp +++ b/test/test_log2.cpp @@ -157,27 +157,6 @@ void test_log2_constexpr() static_assert(log2(u64{UINT64_C(9223372036854775808)}) == 63); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_log2_verified() -{ - static_assert(log2(verified_u8{u8{static_cast(1)}}) == 0); - static_assert(log2(verified_u8{u8{static_cast(128)}}) == 7); - static_assert(log2(verified_u8{u8{static_cast(255)}}) == 7); - - static_assert(log2(verified_u16{u16{static_cast(1024)}}) == 10); - - static_assert(log2(verified_u32{u32{UINT32_C(1048576)}}) == 20); - static_assert(log2(verified_u32{u32{UINT32_C(4294967295)}}) == 31); - - static_assert(log2(verified_u64{u64{UINT64_C(9223372036854775808)}}) == 63); - - using boost::int128::uint128_t; - static_assert(log2(verified_u128{u128{uint128_t{UINT64_C(1099511627776)}}}) == 40); -} - int main() { // Powers of 2 - all types @@ -206,8 +185,5 @@ int main() // Constexpr evaluation test_log2_constexpr(); - // Verified types (consteval) - test_log2_verified(); - return boost::report_errors(); } diff --git a/test/test_midpoint.cpp b/test/test_midpoint.cpp index 32fd755..b8fd555 100644 --- a/test/test_midpoint.cpp +++ b/test/test_midpoint.cpp @@ -251,40 +251,6 @@ void test_midpoint_constexpr() static_assert(midpoint(u64{UINT64_C(1000)}, u64{UINT64_C(3000)}) == u64{UINT64_C(2000)}); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_midpoint_verified() -{ - // verified_u8 - static_assert(midpoint(verified_u8{u8{static_cast(0)}}, - verified_u8{u8{static_cast(10)}}) == verified_u8{u8{static_cast(5)}}); - static_assert(midpoint(verified_u8{u8{static_cast(1)}}, - verified_u8{u8{static_cast(4)}}) == verified_u8{u8{static_cast(2)}}); - static_assert(midpoint(verified_u8{u8{static_cast(4)}}, - verified_u8{u8{static_cast(1)}}) == verified_u8{u8{static_cast(3)}}); - - // verified_u16 - static_assert(midpoint(verified_u16{u16{static_cast(0)}}, - verified_u16{u16{static_cast(65534)}}) == verified_u16{u16{static_cast(32767)}}); - - // verified_u32 - static_assert(midpoint(verified_u32{u32{UINT32_C(100)}}, - verified_u32{u32{UINT32_C(200)}}) == verified_u32{u32{UINT32_C(150)}}); - - // verified_u64 - static_assert(midpoint(verified_u64{u64{UINT64_C(1000)}}, - verified_u64{u64{UINT64_C(3000)}}) == verified_u64{u64{UINT64_C(2000)}}); - - // verified_u128 - using boost::int128::uint128_t; - static_assert(midpoint(verified_u128{u128{uint128_t{0}}}, - verified_u128{u128{uint128_t{10}}}) == verified_u128{u128{uint128_t{5}}}); - static_assert(midpoint(verified_u128{u128{uint128_t{4}}}, - verified_u128{u128{uint128_t{1}}}) == verified_u128{u128{uint128_t{3}}}); -} - int main() { // Equal values - all types @@ -334,8 +300,5 @@ int main() // Constexpr evaluation test_midpoint_constexpr(); - // Verified types (consteval) - test_midpoint_verified(); - return boost::report_errors(); } diff --git a/test/test_remove_trailing_zeros.cpp b/test/test_remove_trailing_zeros.cpp index a6846b5..c771acb 100644 --- a/test/test_remove_trailing_zeros.cpp +++ b/test/test_remove_trailing_zeros.cpp @@ -245,34 +245,6 @@ void test_rtz_constexpr() BOOST_TEST_EQ(r64.number_of_removed_zeros, static_cast(6)); } -// ============================================================================= -// Verified type tests (consteval) -// ============================================================================= - -void test_rtz_verified() -{ - constexpr auto v8 = remove_trailing_zeros(verified_u8{u8{static_cast(50)}}); - BOOST_TEST_EQ(v8.trimmed_number, static_cast(5)); - BOOST_TEST_EQ(v8.number_of_removed_zeros, static_cast(1)); - - constexpr auto v16 = remove_trailing_zeros(verified_u16{u16{static_cast(3000)}}); - BOOST_TEST_EQ(v16.trimmed_number, static_cast(3)); - BOOST_TEST_EQ(v16.number_of_removed_zeros, static_cast(3)); - - constexpr auto v32 = remove_trailing_zeros(verified_u32{u32{UINT32_C(200)}}); - BOOST_TEST_EQ(v32.trimmed_number, UINT32_C(2)); - BOOST_TEST_EQ(v32.number_of_removed_zeros, static_cast(2)); - - constexpr auto v64 = remove_trailing_zeros(verified_u64{u64{UINT64_C(9000000000)}}); - BOOST_TEST_EQ(v64.trimmed_number, UINT64_C(9)); - BOOST_TEST_EQ(v64.number_of_removed_zeros, static_cast(9)); - - using boost::int128::uint128_t; - constexpr auto v128 = remove_trailing_zeros(verified_u128{u128{uint128_t{UINT64_C(100000)}}}); - BOOST_TEST_EQ(v128.trimmed_number, uint128_t{1}); - BOOST_TEST_EQ(v128.number_of_removed_zeros, static_cast(5)); -} - // ============================================================================= // Zero input tests // ============================================================================= @@ -298,17 +270,6 @@ void test_rtz_zero_constexpr() BOOST_TEST_EQ(r32.number_of_removed_zeros, static_cast(0)); } -void test_rtz_zero_verified() -{ - constexpr auto v8 = remove_trailing_zeros(verified_u8{u8{static_cast(0)}}); - BOOST_TEST_EQ(v8.trimmed_number, static_cast(0)); - BOOST_TEST_EQ(v8.number_of_removed_zeros, static_cast(0)); - - constexpr auto v32 = remove_trailing_zeros(verified_u32{u32{UINT32_C(0)}}); - BOOST_TEST_EQ(v32.trimmed_number, UINT32_C(0)); - BOOST_TEST_EQ(v32.number_of_removed_zeros, static_cast(0)); -} - int main() { // Zero input - all types @@ -318,7 +279,6 @@ int main() test_rtz_zero(); test_rtz_zero(); test_rtz_zero_constexpr(); - test_rtz_zero_verified(); // No trailing zeros - all types test_rtz_no_trailing_zeros(); @@ -354,8 +314,5 @@ int main() // Constexpr evaluation test_rtz_constexpr(); - // Verified types (consteval) - test_rtz_verified(); - return boost::report_errors(); } diff --git a/test/test_to_from_be.cpp b/test/test_to_from_be.cpp index 1afb654..16eeca3 100644 --- a/test/test_to_from_be.cpp +++ b/test/test_to_from_be.cpp @@ -11,7 +11,7 @@ import boost.safe_numbers; #else #include -#include +#include #include #include #include @@ -213,51 +213,6 @@ void test_known_byte_patterns() } } -// Verified types: to_be and from_be should work at consteval -void test_verified_consteval() -{ - // verified_u8 round-trip - { - constexpr auto val = verified_u8{u8{0x42}}; - constexpr auto be_val = to_be(val); - constexpr auto rt_val = from_be(be_val); - BOOST_TEST(rt_val == val); - } - - // verified_u16 round-trip - { - constexpr auto val = verified_u16{u16{static_cast(0xABCD)}}; - constexpr auto be_val = to_be(val); - constexpr auto rt_val = from_be(be_val); - BOOST_TEST(rt_val == val); - } - - // verified_u32 round-trip - { - constexpr auto val = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto be_val = to_be(val); - constexpr auto rt_val = from_be(be_val); - BOOST_TEST(rt_val == val); - } - - // verified_u64 round-trip - { - constexpr auto val = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto be_val = to_be(val); - constexpr auto rt_val = from_be(be_val); - BOOST_TEST(rt_val == val); - } - - // Verify known pattern for verified_u32 on little-endian - if constexpr (std::endian::native == std::endian::little) - { - constexpr auto val = verified_u32{u32{0x01020304U}}; - constexpr auto expected = verified_u32{u32{0x04030201U}}; - constexpr auto be_val = to_be(val); - BOOST_TEST(be_val == expected); - } -} - int main() { // Round-trip tests for all unsigned types @@ -289,8 +244,5 @@ int main() // Known byte patterns on little-endian test_known_byte_patterns(); - // Verified types (consteval) - test_verified_consteval(); - return boost::report_errors(); } diff --git a/test/test_to_from_be_bytes.cpp b/test/test_to_from_be_bytes.cpp index 5284969..2b9e097 100644 --- a/test/test_to_from_be_bytes.cpp +++ b/test/test_to_from_be_bytes.cpp @@ -11,7 +11,7 @@ import boost.safe_numbers; #else #include -#include +#include #include #include #include @@ -159,79 +159,6 @@ void test_round_trips() // from_be_bytes with dynamic extent: runtime size mismatch throws // ============================================================================= -// ============================================================================= -// Verified overloads: to_be_bytes and from_be_bytes at compile time -// ============================================================================= - -void test_verified_to_be_bytes() -{ - { - constexpr auto bytes = to_be_bytes(verified_u8{u8{0x42}}); - static_assert(bytes[0] == std::byte{0x42}); - } - { - constexpr auto bytes = to_be_bytes(verified_u16{u16{static_cast(0x0102)}}); - static_assert(bytes[0] == std::byte{0x01}); - static_assert(bytes[1] == std::byte{0x02}); - } - { - constexpr auto bytes = to_be_bytes(verified_u32{u32{0x01020304U}}); - static_assert(bytes[0] == std::byte{0x01}); - static_assert(bytes[1] == std::byte{0x02}); - static_assert(bytes[2] == std::byte{0x03}); - static_assert(bytes[3] == std::byte{0x04}); - } - { - constexpr auto bytes = to_be_bytes(verified_u64{u64{0x0102030405060708ULL}}); - static_assert(bytes[0] == std::byte{0x01}); - static_assert(bytes[1] == std::byte{0x02}); - static_assert(bytes[2] == std::byte{0x03}); - static_assert(bytes[3] == std::byte{0x04}); - static_assert(bytes[4] == std::byte{0x05}); - static_assert(bytes[5] == std::byte{0x06}); - static_assert(bytes[6] == std::byte{0x07}); - static_assert(bytes[7] == std::byte{0x08}); - } -} - -void test_verified_from_be_bytes() -{ - { - constexpr std::array bytes {std::byte{0x42}}; - constexpr auto val = from_be_bytes(std::span{bytes}); - static_assert(static_cast(val) == u8{0x42}); - } - { - constexpr std::array bytes {std::byte{0x01}, std::byte{0x02}, std::byte{0x03}, std::byte{0x04}}; - constexpr auto val = from_be_bytes(std::span{bytes}); - static_assert(static_cast(val) == u32{0x01020304U}); - } - { - constexpr std::array bytes { - std::byte{0x01}, std::byte{0x02}, std::byte{0x03}, std::byte{0x04}, - std::byte{0x05}, std::byte{0x06}, std::byte{0x07}, std::byte{0x08} - }; - constexpr auto val = from_be_bytes(std::span{bytes}); - static_assert(static_cast(val) == u64{0x0102030405060708ULL}); - } -} - -void test_verified_be_bytes_round_trip() -{ - { - constexpr auto original = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto bytes = to_be_bytes(original); - constexpr auto reconstructed = from_be_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } - { - constexpr auto original = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto bytes = to_be_bytes(original); - constexpr auto reconstructed = from_be_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } -} - // ============================================================================= // from_be_bytes with dynamic extent: runtime size mismatch throws // ============================================================================= @@ -269,10 +196,6 @@ int main() test_round_trips(); - test_verified_to_be_bytes(); - test_verified_from_be_bytes(); - test_verified_be_bytes_round_trip(); - test_from_be_bytes_dynamic_size_mismatch(); test_from_be_bytes_dynamic_size_match(); diff --git a/test/test_to_from_le.cpp b/test/test_to_from_le.cpp index 49bf44c..3a4ce5e 100644 --- a/test/test_to_from_le.cpp +++ b/test/test_to_from_le.cpp @@ -11,7 +11,7 @@ import boost.safe_numbers; #else #include -#include +#include #include #include #include @@ -260,50 +260,6 @@ void test_le_be_relationship() } } -// Verified types: to_le and from_le should work at consteval -void test_verified_consteval() -{ - // verified_u8 round-trip - { - constexpr auto val = verified_u8{u8{0x42}}; - constexpr auto le_val = to_le(val); - constexpr auto rt_val = from_le(le_val); - BOOST_TEST(rt_val == val); - } - - // verified_u16 round-trip - { - constexpr auto val = verified_u16{u16{static_cast(0xABCD)}}; - constexpr auto le_val = to_le(val); - constexpr auto rt_val = from_le(le_val); - BOOST_TEST(rt_val == val); - } - - // verified_u32 round-trip - { - constexpr auto val = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto le_val = to_le(val); - constexpr auto rt_val = from_le(le_val); - BOOST_TEST(rt_val == val); - } - - // verified_u64 round-trip - { - constexpr auto val = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto le_val = to_le(val); - constexpr auto rt_val = from_le(le_val); - BOOST_TEST(rt_val == val); - } - - // On little-endian, to_le for verified types should be identity - if constexpr (std::endian::native == std::endian::little) - { - constexpr auto val = verified_u32{u32{0x01020304U}}; - constexpr auto le_val = to_le(val); - BOOST_TEST(le_val == val); - } -} - int main() { // Round-trip tests for all unsigned types @@ -341,8 +297,5 @@ int main() test_le_be_relationship(); test_le_be_relationship(); - // Verified types (consteval) - test_verified_consteval(); - return boost::report_errors(); } diff --git a/test/test_to_from_le_bytes.cpp b/test/test_to_from_le_bytes.cpp index 9e4f05f..61bc147 100644 --- a/test/test_to_from_le_bytes.cpp +++ b/test/test_to_from_le_bytes.cpp @@ -11,7 +11,7 @@ import boost.safe_numbers; #else #include -#include +#include #include #include #include @@ -160,79 +160,6 @@ void test_round_trips() // from_le_bytes with dynamic extent: runtime size mismatch throws // ============================================================================= -// ============================================================================= -// Verified overloads: to_le_bytes and from_le_bytes at compile time -// ============================================================================= - -void test_verified_to_le_bytes() -{ - { - constexpr auto bytes = to_le_bytes(verified_u8{u8{0x42}}); - static_assert(bytes[0] == std::byte{0x42}); - } - { - constexpr auto bytes = to_le_bytes(verified_u16{u16{static_cast(0x0102)}}); - static_assert(bytes[0] == std::byte{0x02}); - static_assert(bytes[1] == std::byte{0x01}); - } - { - constexpr auto bytes = to_le_bytes(verified_u32{u32{0x01020304U}}); - static_assert(bytes[0] == std::byte{0x04}); - static_assert(bytes[1] == std::byte{0x03}); - static_assert(bytes[2] == std::byte{0x02}); - static_assert(bytes[3] == std::byte{0x01}); - } - { - constexpr auto bytes = to_le_bytes(verified_u64{u64{0x0102030405060708ULL}}); - static_assert(bytes[0] == std::byte{0x08}); - static_assert(bytes[1] == std::byte{0x07}); - static_assert(bytes[2] == std::byte{0x06}); - static_assert(bytes[3] == std::byte{0x05}); - static_assert(bytes[4] == std::byte{0x04}); - static_assert(bytes[5] == std::byte{0x03}); - static_assert(bytes[6] == std::byte{0x02}); - static_assert(bytes[7] == std::byte{0x01}); - } -} - -void test_verified_from_le_bytes() -{ - { - constexpr std::array bytes {std::byte{0x42}}; - constexpr auto val = from_le_bytes(std::span{bytes}); - static_assert(static_cast(val) == u8{0x42}); - } - { - constexpr std::array bytes {std::byte{0x04}, std::byte{0x03}, std::byte{0x02}, std::byte{0x01}}; - constexpr auto val = from_le_bytes(std::span{bytes}); - static_assert(static_cast(val) == u32{0x01020304U}); - } - { - constexpr std::array bytes { - std::byte{0x08}, std::byte{0x07}, std::byte{0x06}, std::byte{0x05}, - std::byte{0x04}, std::byte{0x03}, std::byte{0x02}, std::byte{0x01} - }; - constexpr auto val = from_le_bytes(std::span{bytes}); - static_assert(static_cast(val) == u64{0x0102030405060708ULL}); - } -} - -void test_verified_le_bytes_round_trip() -{ - { - constexpr auto original = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto bytes = to_le_bytes(original); - constexpr auto reconstructed = from_le_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } - { - constexpr auto original = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto bytes = to_le_bytes(original); - constexpr auto reconstructed = from_le_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } -} - // ============================================================================= // from_le_bytes with dynamic extent: runtime size mismatch throws // ============================================================================= @@ -270,10 +197,6 @@ int main() test_round_trips(); - test_verified_to_le_bytes(); - test_verified_from_le_bytes(); - test_verified_le_bytes_round_trip(); - test_from_le_bytes_dynamic_size_mismatch(); test_from_le_bytes_dynamic_size_match(); diff --git a/test/test_to_from_ne_bytes.cpp b/test/test_to_from_ne_bytes.cpp index ac36321..22d37ab 100644 --- a/test/test_to_from_ne_bytes.cpp +++ b/test/test_to_from_ne_bytes.cpp @@ -11,7 +11,7 @@ import boost.safe_numbers; #else #include -#include +#include #include #include #include @@ -157,41 +157,6 @@ void test_from_ne_bytes_dynamic_size_match() BOOST_TEST(result == val); } -// ============================================================================= -// Verified overloads -// ============================================================================= - -void test_verified_to_ne_bytes() -{ - // Verify consteval works and produces correct bytes via round-trip - { - constexpr auto original = verified_u32{u32{0x01020304U}}; - constexpr auto bytes = to_ne_bytes(original); - static_assert(bytes.size() == 4); - } - { - constexpr auto original = verified_u64{u64{0x0102030405060708ULL}}; - constexpr auto bytes = to_ne_bytes(original); - static_assert(bytes.size() == 8); - } -} - -void test_verified_from_ne_bytes() -{ - { - constexpr auto original = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto bytes = to_ne_bytes(original); - constexpr auto reconstructed = from_ne_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } - { - constexpr auto original = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto bytes = to_ne_bytes(original); - constexpr auto reconstructed = from_ne_bytes(std::span{bytes}); - static_assert(reconstructed == original); - } -} - int main() { test_to_ne_bytes_matches_platform(); @@ -204,8 +169,5 @@ int main() test_from_ne_bytes_dynamic_size_mismatch(); test_from_ne_bytes_dynamic_size_match(); - test_verified_to_ne_bytes(); - test_verified_from_ne_bytes(); - return boost::report_errors(); } diff --git a/test/test_verified_bit.cpp b/test/test_verified_bit.cpp deleted file mode 100644 index 72b092b..0000000 --- a/test/test_verified_bit.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include -#include -#include - -#endif - -#include - -using namespace boost::safe_numbers; - -// ============================================================================= -// has_single_bit (returns bool - runtime testable) -// ============================================================================= - -template -void test_has_single_bit() -{ - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{0}}), false); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{1}}), true); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{2}}), true); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{3}}), false); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{4}}), true); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{42}}), false); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{64}}), true); - BOOST_TEST_EQ(boost::safe_numbers::has_single_bit(VerifiedT{BasisT{128}}), true); -} - -// ============================================================================= -// bit_width (returns int - runtime testable) -// ============================================================================= - -template -void test_bit_width() -{ - // Compare verified result against basis type result - BOOST_TEST_EQ(boost::safe_numbers::bit_width(VerifiedT{BasisT{0}}), - boost::safe_numbers::bit_width(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::bit_width(VerifiedT{BasisT{1}}), - boost::safe_numbers::bit_width(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::bit_width(VerifiedT{BasisT{42}}), - boost::safe_numbers::bit_width(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::bit_width(VerifiedT{BasisT{255}}), - boost::safe_numbers::bit_width(BasisT{255})); -} - -// ============================================================================= -// countl_zero (returns int - runtime testable) -// ============================================================================= - -template -void test_countl_zero() -{ - BOOST_TEST_EQ(boost::safe_numbers::countl_zero(VerifiedT{BasisT{0}}), - boost::safe_numbers::countl_zero(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::countl_zero(VerifiedT{BasisT{1}}), - boost::safe_numbers::countl_zero(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::countl_zero(VerifiedT{BasisT{42}}), - boost::safe_numbers::countl_zero(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::countl_zero(VerifiedT{BasisT{128}}), - boost::safe_numbers::countl_zero(BasisT{128})); -} - -// ============================================================================= -// countl_one (returns int - runtime testable) -// ============================================================================= - -template -void test_countl_one() -{ - BOOST_TEST_EQ(boost::safe_numbers::countl_one(VerifiedT{BasisT{0}}), - boost::safe_numbers::countl_one(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::countl_one(VerifiedT{BasisT{1}}), - boost::safe_numbers::countl_one(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::countl_one(VerifiedT{BasisT{42}}), - boost::safe_numbers::countl_one(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::countl_one(VerifiedT{BasisT{255}}), - boost::safe_numbers::countl_one(BasisT{255})); -} - -// ============================================================================= -// countr_zero (returns int - runtime testable) -// ============================================================================= - -template -void test_countr_zero() -{ - BOOST_TEST_EQ(boost::safe_numbers::countr_zero(VerifiedT{BasisT{0}}), - boost::safe_numbers::countr_zero(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::countr_zero(VerifiedT{BasisT{1}}), - boost::safe_numbers::countr_zero(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::countr_zero(VerifiedT{BasisT{42}}), - boost::safe_numbers::countr_zero(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::countr_zero(VerifiedT{BasisT{128}}), - boost::safe_numbers::countr_zero(BasisT{128})); -} - -// ============================================================================= -// countr_one (returns int - runtime testable) -// ============================================================================= - -template -void test_countr_one() -{ - BOOST_TEST_EQ(boost::safe_numbers::countr_one(VerifiedT{BasisT{0}}), - boost::safe_numbers::countr_one(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::countr_one(VerifiedT{BasisT{1}}), - boost::safe_numbers::countr_one(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::countr_one(VerifiedT{BasisT{42}}), - boost::safe_numbers::countr_one(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::countr_one(VerifiedT{BasisT{255}}), - boost::safe_numbers::countr_one(BasisT{255})); -} - -// ============================================================================= -// popcount (returns int - runtime testable) -// ============================================================================= - -template -void test_popcount() -{ - BOOST_TEST_EQ(boost::safe_numbers::popcount(VerifiedT{BasisT{0}}), - boost::safe_numbers::popcount(BasisT{0})); - BOOST_TEST_EQ(boost::safe_numbers::popcount(VerifiedT{BasisT{1}}), - boost::safe_numbers::popcount(BasisT{1})); - BOOST_TEST_EQ(boost::safe_numbers::popcount(VerifiedT{BasisT{42}}), - boost::safe_numbers::popcount(BasisT{42})); - BOOST_TEST_EQ(boost::safe_numbers::popcount(VerifiedT{BasisT{255}}), - boost::safe_numbers::popcount(BasisT{255})); -} - -// ============================================================================= -// bit_ceil (returns UnsignedInt - compile-time only for verified types) -// ============================================================================= - -template -consteval auto test_bit_ceil_impl() -> bool -{ - return boost::safe_numbers::bit_ceil(VerifiedT{BasisT{1}}) == VerifiedT{BasisT{1}} - && boost::safe_numbers::bit_ceil(VerifiedT{BasisT{2}}) == VerifiedT{BasisT{2}} - && boost::safe_numbers::bit_ceil(VerifiedT{BasisT{3}}) == VerifiedT{BasisT{4}} - && boost::safe_numbers::bit_ceil(VerifiedT{BasisT{5}}) == VerifiedT{BasisT{8}} - && boost::safe_numbers::bit_ceil(VerifiedT{BasisT{42}}) == VerifiedT{BasisT{64}} - && boost::safe_numbers::bit_ceil(VerifiedT{BasisT{128}}) == VerifiedT{BasisT{128}}; -} - -static_assert(test_bit_ceil_impl()); -static_assert(test_bit_ceil_impl()); -static_assert(test_bit_ceil_impl()); -static_assert(test_bit_ceil_impl()); -static_assert(test_bit_ceil_impl()); - -// ============================================================================= -// bit_floor (returns UnsignedInt - compile-time only for verified types) -// ============================================================================= - -template -consteval auto test_bit_floor_impl() -> bool -{ - return boost::safe_numbers::bit_floor(VerifiedT{BasisT{0}}) == VerifiedT{BasisT{0}} - && boost::safe_numbers::bit_floor(VerifiedT{BasisT{1}}) == VerifiedT{BasisT{1}} - && boost::safe_numbers::bit_floor(VerifiedT{BasisT{3}}) == VerifiedT{BasisT{2}} - && boost::safe_numbers::bit_floor(VerifiedT{BasisT{7}}) == VerifiedT{BasisT{4}} - && boost::safe_numbers::bit_floor(VerifiedT{BasisT{42}}) == VerifiedT{BasisT{32}} - && boost::safe_numbers::bit_floor(VerifiedT{BasisT{128}}) == VerifiedT{BasisT{128}}; -} - -static_assert(test_bit_floor_impl()); -static_assert(test_bit_floor_impl()); -static_assert(test_bit_floor_impl()); -static_assert(test_bit_floor_impl()); -static_assert(test_bit_floor_impl()); - -// ============================================================================= -// rotl (returns UnsignedInt - compile-time only, non-bounded only) -// ============================================================================= - -template -consteval auto test_rotl_impl() -> bool -{ - // rotl(1, 0) == 1 - // rotl(1, 1) == 2 - return boost::safe_numbers::rotl(VerifiedT{BasisT{1}}, 0) == VerifiedT{BasisT{1}} - && boost::safe_numbers::rotl(VerifiedT{BasisT{1}}, 1) == VerifiedT{BasisT{2}}; -} - -static_assert(test_rotl_impl()); -static_assert(test_rotl_impl()); -static_assert(test_rotl_impl()); -static_assert(test_rotl_impl()); -static_assert(test_rotl_impl()); - -// ============================================================================= -// rotr (returns UnsignedInt - compile-time only, non-bounded only) -// ============================================================================= - -template -consteval auto test_rotr_impl() -> bool -{ - // rotr(2, 1) == 1 - return boost::safe_numbers::rotr(VerifiedT{BasisT{2}}, 0) == VerifiedT{BasisT{2}} - && boost::safe_numbers::rotr(VerifiedT{BasisT{2}}, 1) == VerifiedT{BasisT{1}}; -} - -static_assert(test_rotr_impl()); -static_assert(test_rotr_impl()); -static_assert(test_rotr_impl()); -static_assert(test_rotr_impl()); -static_assert(test_rotr_impl()); - -// ============================================================================= -// byteswap (returns UnsignedInt - compile-time only, non-bounded only) -// ============================================================================= - -template -consteval auto test_byteswap_impl() -> bool -{ - // byteswap(0) == 0 for any width - return boost::safe_numbers::byteswap(VerifiedT{BasisT{0}}) == VerifiedT{BasisT{0}}; -} - -static_assert(test_byteswap_impl()); -static_assert(test_byteswap_impl()); -static_assert(test_byteswap_impl()); -static_assert(test_byteswap_impl()); -static_assert(test_byteswap_impl()); - -// ============================================================================= -// bitswap (returns Int - compile-time only, non-bounded only) -// ============================================================================= - -template -consteval auto test_bitswap_impl() -> bool -{ - // bitswap(0) == 0 for any width - return boost::safe_numbers::bitswap(VerifiedT{BasisT{0}}) == VerifiedT{BasisT{0}}; -} - -static_assert(test_bitswap_impl()); -static_assert(test_bitswap_impl()); -static_assert(test_bitswap_impl()); -static_assert(test_bitswap_impl()); -static_assert(test_bitswap_impl()); - -// ============================================================================= -// Main - runtime tests for functions returning int/bool -// ============================================================================= - -int main() -{ - test_has_single_bit(); - test_has_single_bit(); - test_has_single_bit(); - test_has_single_bit(); - test_has_single_bit(); - - test_bit_width(); - test_bit_width(); - test_bit_width(); - test_bit_width(); - test_bit_width(); - - test_countl_zero(); - test_countl_zero(); - test_countl_zero(); - test_countl_zero(); - test_countl_zero(); - - test_countl_one(); - test_countl_one(); - test_countl_one(); - test_countl_one(); - test_countl_one(); - - test_countr_zero(); - test_countr_zero(); - test_countr_zero(); - test_countr_zero(); - test_countr_zero(); - - test_countr_one(); - test_countr_one(); - test_countr_one(); - test_countr_one(); - test_countr_one(); - - test_popcount(); - test_popcount(); - test_popcount(); - test_popcount(); - test_popcount(); - - return boost::report_errors(); -} diff --git a/test/test_verified_charconv.cpp b/test/test_verified_charconv.cpp deleted file mode 100644 index 97e8e74..0000000 --- a/test/test_verified_charconv.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include -#include -#include - -#endif - -#include - -using namespace boost::safe_numbers; - -// ============================================================================= -// to_chars tests (constexpr - runtime testable with verified types) -// ============================================================================= - -template -void test_to_chars() -{ - constexpr auto val = VerifiedT{BasisT{42}}; - - char buffer[256]; - const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val); - BOOST_TEST(r.ec == std::errc{}); - - const auto len = static_cast(r.ptr - buffer); - BOOST_TEST_EQ(len, std::size_t{2}); - BOOST_TEST_EQ(buffer[0], '4'); - BOOST_TEST_EQ(buffer[1], '2'); -} - -template -void test_to_chars_zero() -{ - constexpr auto val = VerifiedT{BasisT{0}}; - - char buffer[256]; - const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val); - BOOST_TEST(r.ec == std::errc{}); - - const auto len = static_cast(r.ptr - buffer); - BOOST_TEST_EQ(len, std::size_t{1}); - BOOST_TEST_EQ(buffer[0], '0'); -} - -template -void test_to_chars_255() -{ - constexpr auto val = VerifiedT{BasisT{255}}; - - char buffer[256]; - const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val); - BOOST_TEST(r.ec == std::errc{}); - - const auto len = static_cast(r.ptr - buffer); - BOOST_TEST_EQ(len, std::size_t{3}); - BOOST_TEST_EQ(buffer[0], '2'); - BOOST_TEST_EQ(buffer[1], '5'); - BOOST_TEST_EQ(buffer[2], '5'); -} - -template -void test_to_chars_hex() -{ - constexpr auto val = VerifiedT{BasisT{255}}; - - char buffer[256]; - const auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val, 16); - BOOST_TEST(r.ec == std::errc{}); - - const auto len = static_cast(r.ptr - buffer); - BOOST_TEST_EQ(len, std::size_t{2}); - BOOST_TEST_EQ(buffer[0], 'f'); - BOOST_TEST_EQ(buffer[1], 'f'); -} - -// ============================================================================= -// from_chars tests (consteval - compile-time only for verified types) -// ============================================================================= - -template -consteval auto test_from_chars_impl() -> bool -{ - const char str[] = "42"; - auto val = VerifiedT{BasisT{0}}; - const auto r = boost::charconv::from_chars(str, str + 2, val); - return r.ec == std::errc{} && val == VerifiedT{BasisT{42}}; -} - -template -consteval auto test_from_chars_zero_impl() -> bool -{ - const char str[] = "0"; - auto val = VerifiedT{BasisT{1}}; - const auto r = boost::charconv::from_chars(str, str + 1, val); - return r.ec == std::errc{} && val == VerifiedT{BasisT{0}}; -} - -template -consteval auto test_from_chars_255_impl() -> bool -{ - const char str[] = "255"; - auto val = VerifiedT{BasisT{0}}; - const auto r = boost::charconv::from_chars(str, str + 3, val); - return r.ec == std::errc{} && val == VerifiedT{BasisT{255}}; -} - -template -consteval auto test_from_chars_hex_impl() -> bool -{ - const char str[] = "ff"; - auto val = VerifiedT{BasisT{0}}; - const auto r = boost::charconv::from_chars(str, str + 2, val, 16); - return r.ec == std::errc{} && val == VerifiedT{BasisT{255}}; -} - -// --- from_chars base 10 --- -static_assert(test_from_chars_impl()); -static_assert(test_from_chars_impl()); -static_assert(test_from_chars_impl()); -static_assert(test_from_chars_impl()); -static_assert(test_from_chars_impl()); - -// --- from_chars zero --- -static_assert(test_from_chars_zero_impl()); -static_assert(test_from_chars_zero_impl()); -static_assert(test_from_chars_zero_impl()); -static_assert(test_from_chars_zero_impl()); -static_assert(test_from_chars_zero_impl()); - -// --- from_chars 255 --- -static_assert(test_from_chars_255_impl()); -static_assert(test_from_chars_255_impl()); -static_assert(test_from_chars_255_impl()); -static_assert(test_from_chars_255_impl()); -static_assert(test_from_chars_255_impl()); - -// --- from_chars hex --- -static_assert(test_from_chars_hex_impl()); -static_assert(test_from_chars_hex_impl()); -static_assert(test_from_chars_hex_impl()); -static_assert(test_from_chars_hex_impl()); -static_assert(test_from_chars_hex_impl()); - -// --- from_chars with bounded type --- -using test_bounded = bounded_uint<0u, 255u>; -using test_verified_bounded = verified_bounded_integer<0u, 255u>; - -static_assert(test_from_chars_impl()); -static_assert(test_from_chars_zero_impl()); -static_assert(test_from_chars_255_impl()); -static_assert(test_from_chars_hex_impl()); - -// ============================================================================= -// Main - runtime tests for to_chars -// ============================================================================= - -int main() -{ - test_to_chars(); - test_to_chars(); - test_to_chars(); - test_to_chars(); - test_to_chars(); - - test_to_chars_zero(); - test_to_chars_zero(); - test_to_chars_zero(); - test_to_chars_zero(); - test_to_chars_zero(); - - test_to_chars_255(); - test_to_chars_255(); - test_to_chars_255(); - test_to_chars_255(); - test_to_chars_255(); - - test_to_chars_hex(); - test_to_chars_hex(); - test_to_chars_hex(); - test_to_chars_hex(); - test_to_chars_hex(); - - // Bounded verified types - test_to_chars(); - test_to_chars_zero(); - test_to_chars_255(); - test_to_chars_hex(); - - return boost::report_errors(); -} diff --git a/test/test_verified_fmt_format.cpp b/test/test_verified_fmt_format.cpp deleted file mode 100644 index 29be232..0000000 --- a/test/test_verified_fmt_format.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wfloat-equal" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wconversion" -#endif - -#define FMT_HEADER_ONLY - -#if __has_include() - -#include -#include -#include -#include - -using namespace boost::safe_numbers; - -template -void test() -{ - constexpr auto x = VerifiedT{BasisT{42}}; - - BOOST_TEST_CSTR_EQ(fmt::format("{}", x).c_str(), "42"); - BOOST_TEST_CSTR_EQ(fmt::format("{:08x}", x).c_str(), "0000002a"); - BOOST_TEST_CSTR_EQ(fmt::format("{:#010b}", x).c_str(), "0b00101010"); -} - -template -void test_zero() -{ - constexpr auto x = VerifiedT{BasisT{0}}; - - BOOST_TEST_CSTR_EQ(fmt::format("{}", x).c_str(), "0"); -} - -template -void test_255() -{ - constexpr auto x = VerifiedT{BasisT{255}}; - - BOOST_TEST_CSTR_EQ(fmt::format("{}", x).c_str(), "255"); - BOOST_TEST_CSTR_EQ(fmt::format("{:x}", x).c_str(), "ff"); -} - -int main() -{ - test(); - test(); - test(); - test(); - test(); - - test_zero(); - test_zero(); - test_zero(); - test_zero(); - test_zero(); - - test_255(); - test_255(); - test_255(); - test_255(); - test_255(); - - // Bounded verified type - using test_bounded = bounded_uint<0u, 255u>; - using test_verified_bounded = verified_bounded_integer<0u, 255u>; - - test(); - test_zero(); - test_255(); - - return boost::report_errors(); -} - -#else - -int main() -{ - return 0; -} - -#endif diff --git a/test/test_verified_integers.cpp b/test/test_verified_integers.cpp deleted file mode 100644 index 2f52652..0000000 --- a/test/test_verified_integers.cpp +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include -#include -#include -#include - -#endif - -#include - -using namespace boost::safe_numbers; - -// ============================================================================= -// Construction tests (consteval - verified via constexpr variables) -// ============================================================================= - -template -void test_construction() -{ - constexpr auto val1 = VerifiedT{BasisT{0}}; - constexpr auto val2 = VerifiedT{BasisT{42}}; - constexpr auto val3 = VerifiedT{BasisT{100}}; - - BOOST_TEST(val1 == VerifiedT{BasisT{0}}); - BOOST_TEST(val2 == VerifiedT{BasisT{42}}); - BOOST_TEST(val3 == VerifiedT{BasisT{100}}); - - // From underlying type - using underlying = detail::underlying_type_t; - constexpr auto val4 = VerifiedT{underlying{42}}; - BOOST_TEST(val4 == val2); -} - -// ============================================================================= -// Conversion tests (constexpr - runtime testable) -// ============================================================================= - -template -void test_conversions() -{ - using underlying = detail::underlying_type_t; - - constexpr auto val = VerifiedT{BasisT{42}}; - - // Convert to BasisType - constexpr auto basis_val = static_cast(val); - BOOST_TEST(basis_val == BasisT{42}); - - // Convert to underlying type - constexpr auto raw_val = static_cast(val); - BOOST_TEST(raw_val == underlying{42}); -} - -// ============================================================================= -// Comparison tests (constexpr - runtime testable) -// ============================================================================= - -template -void test_comparisons() -{ - constexpr auto a = VerifiedT{BasisT{10}}; - constexpr auto b = VerifiedT{BasisT{20}}; - constexpr auto c = VerifiedT{BasisT{10}}; - - BOOST_TEST(a == c); - BOOST_TEST(a != b); - BOOST_TEST(a < b); - BOOST_TEST(a <= b); - BOOST_TEST(a <= c); - BOOST_TEST(b > a); - BOOST_TEST(b >= a); - BOOST_TEST(a >= c); - BOOST_TEST((a <=> c) == std::strong_ordering::equal); - BOOST_TEST((a <=> b) == std::strong_ordering::less); - BOOST_TEST((b <=> a) == std::strong_ordering::greater); -} - -// ============================================================================= -// Arithmetic tests (consteval - verified via static_assert) -// ============================================================================= - -template -consteval auto test_addition_impl() -> bool -{ - const auto a = VerifiedT{BasisT{10}}; - const auto b = VerifiedT{BasisT{20}}; - const auto c = a + b; - return c == VerifiedT{BasisT{30}}; -} - -template -consteval auto test_subtraction_impl() -> bool -{ - const auto a = VerifiedT{BasisT{30}}; - const auto b = VerifiedT{BasisT{10}}; - const auto c = a - b; - return c == VerifiedT{BasisT{20}}; -} - -template -consteval auto test_multiplication_impl() -> bool -{ - const auto a = VerifiedT{BasisT{5}}; - const auto b = VerifiedT{BasisT{6}}; - const auto c = a * b; - return c == VerifiedT{BasisT{30}}; -} - -template -consteval auto test_division_impl() -> bool -{ - const auto a = VerifiedT{BasisT{30}}; - const auto b = VerifiedT{BasisT{5}}; - const auto c = a / b; - return c == VerifiedT{BasisT{6}}; -} - -template -consteval auto test_modulo_impl() -> bool -{ - const auto a = VerifiedT{BasisT{17}}; - const auto b = VerifiedT{BasisT{5}}; - const auto c = a % b; - return c == VerifiedT{BasisT{2}}; -} - -// --- Addition --- -static_assert(test_addition_impl()); -static_assert(test_addition_impl()); -static_assert(test_addition_impl()); -static_assert(test_addition_impl()); -static_assert(test_addition_impl()); - -// --- Subtraction --- -static_assert(test_subtraction_impl()); -static_assert(test_subtraction_impl()); -static_assert(test_subtraction_impl()); -static_assert(test_subtraction_impl()); -static_assert(test_subtraction_impl()); - -// --- Multiplication --- -static_assert(test_multiplication_impl()); -static_assert(test_multiplication_impl()); -static_assert(test_multiplication_impl()); -static_assert(test_multiplication_impl()); -static_assert(test_multiplication_impl()); - -// --- Division --- -static_assert(test_division_impl()); -static_assert(test_division_impl()); -static_assert(test_division_impl()); -static_assert(test_division_impl()); -static_assert(test_division_impl()); - -// --- Modulo --- -static_assert(test_modulo_impl()); -static_assert(test_modulo_impl()); -static_assert(test_modulo_impl()); -static_assert(test_modulo_impl()); -static_assert(test_modulo_impl()); - -// ============================================================================= -// Compound assignment tests (consteval - verified via static_assert) -// ============================================================================= - -template -consteval auto test_compound_addition_impl() -> bool -{ - auto a = VerifiedT{BasisT{10}}; - a += VerifiedT{BasisT{20}}; - return a == VerifiedT{BasisT{30}}; -} - -template -consteval auto test_compound_subtraction_impl() -> bool -{ - auto a = VerifiedT{BasisT{30}}; - a -= VerifiedT{BasisT{10}}; - return a == VerifiedT{BasisT{20}}; -} - -template -consteval auto test_compound_multiplication_impl() -> bool -{ - auto a = VerifiedT{BasisT{5}}; - a *= VerifiedT{BasisT{6}}; - return a == VerifiedT{BasisT{30}}; -} - -template -consteval auto test_compound_division_impl() -> bool -{ - auto a = VerifiedT{BasisT{30}}; - a /= VerifiedT{BasisT{5}}; - return a == VerifiedT{BasisT{6}}; -} - -template -consteval auto test_compound_modulo_impl() -> bool -{ - auto a = VerifiedT{BasisT{17}}; - a %= VerifiedT{BasisT{5}}; - return a == VerifiedT{BasisT{2}}; -} - -// --- Compound addition --- -static_assert(test_compound_addition_impl()); -static_assert(test_compound_addition_impl()); -static_assert(test_compound_addition_impl()); -static_assert(test_compound_addition_impl()); -static_assert(test_compound_addition_impl()); - -// --- Compound subtraction --- -static_assert(test_compound_subtraction_impl()); -static_assert(test_compound_subtraction_impl()); -static_assert(test_compound_subtraction_impl()); -static_assert(test_compound_subtraction_impl()); -static_assert(test_compound_subtraction_impl()); - -// --- Compound multiplication --- -static_assert(test_compound_multiplication_impl()); -static_assert(test_compound_multiplication_impl()); -static_assert(test_compound_multiplication_impl()); -static_assert(test_compound_multiplication_impl()); -static_assert(test_compound_multiplication_impl()); - -// --- Compound division --- -static_assert(test_compound_division_impl()); -static_assert(test_compound_division_impl()); -static_assert(test_compound_division_impl()); -static_assert(test_compound_division_impl()); -static_assert(test_compound_division_impl()); - -// --- Compound modulo --- -static_assert(test_compound_modulo_impl()); -static_assert(test_compound_modulo_impl()); -static_assert(test_compound_modulo_impl()); -static_assert(test_compound_modulo_impl()); -static_assert(test_compound_modulo_impl()); - -// ============================================================================= -// Increment/decrement tests (consteval - verified via static_assert) -// ============================================================================= - -template -consteval auto test_prefix_increment_impl() -> bool -{ - auto a = VerifiedT{BasisT{5}}; - ++a; - return a == VerifiedT{BasisT{6}}; -} - -template -consteval auto test_postfix_increment_impl() -> bool -{ - auto a = VerifiedT{BasisT{5}}; - const auto old = a++; - return a == VerifiedT{BasisT{6}} && old == VerifiedT{BasisT{5}}; -} - -template -consteval auto test_prefix_decrement_impl() -> bool -{ - auto a = VerifiedT{BasisT{5}}; - --a; - return a == VerifiedT{BasisT{4}}; -} - -template -consteval auto test_postfix_decrement_impl() -> bool -{ - auto a = VerifiedT{BasisT{5}}; - const auto old = a--; - return a == VerifiedT{BasisT{4}} && old == VerifiedT{BasisT{5}}; -} - -// --- Prefix increment --- -static_assert(test_prefix_increment_impl()); -static_assert(test_prefix_increment_impl()); -static_assert(test_prefix_increment_impl()); -static_assert(test_prefix_increment_impl()); -static_assert(test_prefix_increment_impl()); - -// --- Postfix increment --- -static_assert(test_postfix_increment_impl()); -static_assert(test_postfix_increment_impl()); -static_assert(test_postfix_increment_impl()); -static_assert(test_postfix_increment_impl()); -static_assert(test_postfix_increment_impl()); - -// --- Prefix decrement --- -static_assert(test_prefix_decrement_impl()); -static_assert(test_prefix_decrement_impl()); -static_assert(test_prefix_decrement_impl()); -static_assert(test_prefix_decrement_impl()); -static_assert(test_prefix_decrement_impl()); - -// --- Postfix decrement --- -static_assert(test_postfix_decrement_impl()); -static_assert(test_postfix_decrement_impl()); -static_assert(test_postfix_decrement_impl()); -static_assert(test_postfix_decrement_impl()); -static_assert(test_postfix_decrement_impl()); - -// ============================================================================= -// Bounded integer tests (consteval - verified via static_assert) -// ============================================================================= - -using test_bounded = bounded_uint<0u, 100u>; -using test_verified_bounded = verified_bounded_integer<0u, 100u>; - -static_assert(test_addition_impl()); -static_assert(test_subtraction_impl()); -static_assert(test_multiplication_impl()); -static_assert(test_division_impl()); -static_assert(test_modulo_impl()); - -static_assert(test_compound_addition_impl()); -static_assert(test_compound_subtraction_impl()); -static_assert(test_compound_multiplication_impl()); -static_assert(test_compound_division_impl()); -static_assert(test_compound_modulo_impl()); - -static_assert(test_prefix_increment_impl()); -static_assert(test_postfix_increment_impl()); -static_assert(test_prefix_decrement_impl()); -static_assert(test_postfix_decrement_impl()); - -// ============================================================================= -// Main - runtime tests for constexpr operations (comparisons, conversions) -// ============================================================================= - -int main() -{ - test_construction(); - test_construction(); - test_construction(); - test_construction(); - test_construction(); - - test_conversions(); - test_conversions(); - test_conversions(); - test_conversions(); - test_conversions(); - - test_comparisons(); - test_comparisons(); - test_comparisons(); - test_comparisons(); - test_comparisons(); - - test_comparisons(); - - return boost::report_errors(); -} diff --git a/test/test_verified_limits.cpp b/test/test_verified_limits.cpp deleted file mode 100644 index 21ec6e0..0000000 --- a/test/test_verified_limits.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include - -#endif - -#include -#include - -using namespace boost::safe_numbers; - -// ============================================================================= -// Compile-time tests via static_assert -// ============================================================================= - -template -consteval auto test_limits_properties_impl() -> bool -{ - using vlimits = std::numeric_limits; - using blimits = std::numeric_limits; - - return vlimits::is_specialized == blimits::is_specialized && - vlimits::is_signed == blimits::is_signed && - vlimits::is_integer == blimits::is_integer && - vlimits::is_exact == blimits::is_exact && - vlimits::has_infinity == blimits::has_infinity && - vlimits::has_quiet_NaN == blimits::has_quiet_NaN && - vlimits::has_signaling_NaN == blimits::has_signaling_NaN && - vlimits::is_iec559 == blimits::is_iec559 && - vlimits::is_bounded == blimits::is_bounded && - vlimits::is_modulo == blimits::is_modulo && - vlimits::digits == blimits::digits && - vlimits::digits10 == blimits::digits10 && - vlimits::max_digits10 == blimits::max_digits10 && - vlimits::radix == blimits::radix && - vlimits::min_exponent == blimits::min_exponent && - vlimits::min_exponent10 == blimits::min_exponent10 && - vlimits::max_exponent == blimits::max_exponent && - vlimits::max_exponent10 == blimits::max_exponent10 && - vlimits::traps == blimits::traps && - vlimits::tinyness_before == blimits::tinyness_before; -} - -template -consteval auto test_limits_functions_impl() -> bool -{ - using vlimits = std::numeric_limits; - using blimits = std::numeric_limits; - - return vlimits::min() == VerifiedT{blimits::min()} && - vlimits::max() == VerifiedT{blimits::max()} && - vlimits::lowest() == VerifiedT{blimits::lowest()} && - vlimits::epsilon() == VerifiedT{blimits::epsilon()} && - vlimits::round_error() == VerifiedT{blimits::round_error()} && - vlimits::infinity() == VerifiedT{blimits::infinity()} && - vlimits::quiet_NaN() == VerifiedT{blimits::quiet_NaN()} && - vlimits::signaling_NaN() == VerifiedT{blimits::signaling_NaN()} && - vlimits::denorm_min() == VerifiedT{blimits::denorm_min()}; -} - -// --- Properties --- -static_assert(test_limits_properties_impl()); -static_assert(test_limits_properties_impl()); -static_assert(test_limits_properties_impl()); -static_assert(test_limits_properties_impl()); -static_assert(test_limits_properties_impl()); - -// --- Functions --- -static_assert(test_limits_functions_impl()); -static_assert(test_limits_functions_impl()); -static_assert(test_limits_functions_impl()); -static_assert(test_limits_functions_impl()); -static_assert(test_limits_functions_impl()); - -// --- Bounded verified types --- -using test_bounded = bounded_uint<0u, 255u>; -using test_verified_bounded = verified_bounded_integer<0u, 255u>; - -static_assert(test_limits_properties_impl()); -static_assert(test_limits_functions_impl()); - -using test_bounded_narrow = bounded_uint<10u, 200u>; -using test_verified_bounded_narrow = verified_bounded_integer<10u, 200u>; - -static_assert(test_limits_properties_impl()); -static_assert(test_limits_functions_impl()); - -// ============================================================================= -// Runtime tests -// ============================================================================= - -template -void test_properties() -{ - using vlimits = std::numeric_limits; - using blimits = std::numeric_limits; - - BOOST_TEST_EQ(vlimits::is_specialized, blimits::is_specialized); - BOOST_TEST_EQ(vlimits::is_signed, blimits::is_signed); - BOOST_TEST_EQ(vlimits::is_integer, blimits::is_integer); - BOOST_TEST_EQ(vlimits::is_exact, blimits::is_exact); - BOOST_TEST_EQ(vlimits::has_infinity, blimits::has_infinity); - BOOST_TEST_EQ(vlimits::has_quiet_NaN, blimits::has_quiet_NaN); - BOOST_TEST_EQ(vlimits::has_signaling_NaN, blimits::has_signaling_NaN); - - #if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L))) - BOOST_TEST(vlimits::has_denorm == blimits::has_denorm); - BOOST_TEST(vlimits::has_denorm_loss == blimits::has_denorm_loss); - #endif - - BOOST_TEST(vlimits::round_style == blimits::round_style); - - BOOST_TEST_EQ(vlimits::is_iec559, blimits::is_iec559); - BOOST_TEST_EQ(vlimits::is_bounded, blimits::is_bounded); - BOOST_TEST_EQ(vlimits::is_modulo, blimits::is_modulo); - BOOST_TEST_EQ(vlimits::digits, blimits::digits); - BOOST_TEST_EQ(vlimits::digits10, blimits::digits10); - BOOST_TEST_EQ(vlimits::max_digits10, blimits::max_digits10); - BOOST_TEST_EQ(vlimits::radix, blimits::radix); - BOOST_TEST_EQ(vlimits::min_exponent, blimits::min_exponent); - BOOST_TEST_EQ(vlimits::min_exponent10, blimits::min_exponent10); - BOOST_TEST_EQ(vlimits::max_exponent, blimits::max_exponent); - BOOST_TEST_EQ(vlimits::max_exponent10, blimits::max_exponent10); - BOOST_TEST_EQ(vlimits::traps, blimits::traps); - BOOST_TEST_EQ(vlimits::tinyness_before, blimits::tinyness_before); -} - -template -void test_functions() -{ - using vlimits = std::numeric_limits; - using blimits = std::numeric_limits; - - BOOST_TEST(vlimits::min() == VerifiedT{blimits::min()}); - BOOST_TEST(vlimits::max() == VerifiedT{blimits::max()}); - BOOST_TEST(vlimits::lowest() == VerifiedT{blimits::lowest()}); - BOOST_TEST(vlimits::epsilon() == VerifiedT{blimits::epsilon()}); - BOOST_TEST(vlimits::round_error() == VerifiedT{blimits::round_error()}); - BOOST_TEST(vlimits::infinity() == VerifiedT{blimits::infinity()}); - BOOST_TEST(vlimits::quiet_NaN() == VerifiedT{blimits::quiet_NaN()}); - BOOST_TEST(vlimits::signaling_NaN() == VerifiedT{blimits::signaling_NaN()}); - BOOST_TEST(vlimits::denorm_min() == VerifiedT{blimits::denorm_min()}); -} - -int main() -{ - test_properties(); - test_properties(); - test_properties(); - test_properties(); - test_properties(); - - test_functions(); - test_functions(); - test_functions(); - test_functions(); - test_functions(); - - // Bounded verified types - test_properties(); - test_functions(); - - test_properties(); - test_functions(); - - return boost::report_errors(); -} diff --git a/test/test_verified_mixed_ops.cpp b/test/test_verified_mixed_ops.cpp deleted file mode 100644 index 40550c3..0000000 --- a/test/test_verified_mixed_ops.cpp +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include -#include -#include - -#endif - -#include - -using namespace boost::safe_numbers; - -// ============================================================================= -// Mixed arithmetic: verified_uN op uN -> uN -// ============================================================================= - -template -void test_verified_op_basis_arithmetic() -{ - constexpr auto v10 = VerifiedT{BasisT{10}}; - constexpr auto v20 = VerifiedT{BasisT{20}}; - constexpr auto v5 = VerifiedT{BasisT{5}}; - constexpr auto v17 = VerifiedT{BasisT{17}}; - - const auto b3 = BasisT{3}; - const auto b5 = BasisT{5}; - const auto b7 = BasisT{7}; - - // verified + basis -> basis - BOOST_TEST((v10 + b7) == BasisT{17}); - - // verified - basis -> basis - BOOST_TEST((v20 - b7) == BasisT{13}); - - // verified * basis -> basis - BOOST_TEST((v5 * b3) == BasisT{15}); - - // verified / basis -> basis - BOOST_TEST((v20 / b5) == BasisT{4}); - - // verified % basis -> basis - BOOST_TEST((v17 % b5) == BasisT{2}); -} - -// ============================================================================= -// Mixed arithmetic: uN op verified_uN -> uN -// ============================================================================= - -template -void test_basis_op_verified_arithmetic() -{ - constexpr auto v3 = VerifiedT{BasisT{3}}; - constexpr auto v5 = VerifiedT{BasisT{5}}; - constexpr auto v7 = VerifiedT{BasisT{7}}; - - const auto b10 = BasisT{10}; - const auto b17 = BasisT{17}; - const auto b20 = BasisT{20}; - - // basis + verified -> basis - BOOST_TEST((b10 + v7) == BasisT{17}); - - // basis - verified -> basis - BOOST_TEST((b20 - v7) == BasisT{13}); - - // basis * verified -> basis - BOOST_TEST((b10 * v3) == BasisT{30}); - - // basis / verified -> basis - BOOST_TEST((b20 / v5) == BasisT{4}); - - // basis % verified -> basis - BOOST_TEST((b17 % v5) == BasisT{2}); -} - -// ============================================================================= -// Asymmetric operand tests (ensures both operands are used correctly) -// ============================================================================= - -template -void test_asymmetric_operands() -{ - // Use values where a op b != b op a for non-commutative ops (-, /, %) - constexpr auto v30 = VerifiedT{BasisT{30}}; - constexpr auto v7 = VerifiedT{BasisT{7}}; - - const auto b10 = BasisT{10}; - - // verified - basis: 30 - 10 = 20 - BOOST_TEST((v30 - b10) == BasisT{20}); - - // basis - verified: 10 - 7 = 3 - BOOST_TEST((b10 - v7) == BasisT{3}); - - // verified / basis: 30 / 10 = 3 - BOOST_TEST((v30 / b10) == BasisT{3}); - - // basis / verified: 10 / 7 = 1 - BOOST_TEST((b10 / v7) == BasisT{1}); - - // verified % basis: 30 % 10 = 0 - BOOST_TEST((v30 % b10) == BasisT{0}); - - // basis % verified: 10 % 7 = 3 - BOOST_TEST((b10 % v7) == BasisT{3}); -} - -// ============================================================================= -// Mixed comparisons: verified_uN vs uN -// ============================================================================= - -template -void test_mixed_comparisons() -{ - constexpr auto v10 = VerifiedT{BasisT{10}}; - constexpr auto v20 = VerifiedT{BasisT{20}}; - - const auto b10 = BasisT{10}; - const auto b20 = BasisT{20}; - const auto b5 = BasisT{5}; - - // verified == basis - BOOST_TEST(v10 == b10); - BOOST_TEST(!(v10 == b20)); - - // verified != basis - BOOST_TEST(v10 != b20); - BOOST_TEST(!(v10 != b10)); - - // verified < basis - BOOST_TEST(v10 < b20); - BOOST_TEST(!(v20 < b10)); - - // verified <= basis - BOOST_TEST(v10 <= b10); - BOOST_TEST(v10 <= b20); - BOOST_TEST(!(v20 <= b5)); - - // verified > basis - BOOST_TEST(v20 > b10); - BOOST_TEST(!(v10 > b20)); - - // verified >= basis - BOOST_TEST(v10 >= b10); - BOOST_TEST(v20 >= b10); - BOOST_TEST(!(v10 >= b20)); - - // verified <=> basis - BOOST_TEST((v10 <=> b10) == std::strong_ordering::equal); - BOOST_TEST((v10 <=> b20) == std::strong_ordering::less); - BOOST_TEST((v20 <=> b10) == std::strong_ordering::greater); - - // basis == verified - BOOST_TEST(b10 == v10); - BOOST_TEST(!(b20 == v10)); - - // basis != verified - BOOST_TEST(b20 != v10); - BOOST_TEST(!(b10 != v10)); - - // basis < verified - BOOST_TEST(b10 < v20); - BOOST_TEST(!(b20 < v10)); - - // basis <= verified - BOOST_TEST(b10 <= v10); - BOOST_TEST(b10 <= v20); - - // basis > verified - BOOST_TEST(b20 > v10); - BOOST_TEST(!(b10 > v20)); - - // basis >= verified - BOOST_TEST(b10 >= v10); - BOOST_TEST(b20 >= v10); - - // basis <=> verified - BOOST_TEST((b10 <=> v10) == std::strong_ordering::equal); - BOOST_TEST((b10 <=> v20) == std::strong_ordering::less); - BOOST_TEST((b20 <=> v10) == std::strong_ordering::greater); -} - -// ============================================================================= -// Mixed ops with bounded_uint types -// ============================================================================= - -void test_bounded_mixed_arithmetic() -{ - using bounded_t = bounded_uint<0u, 100u>; - using verified_bounded_t = verified_bounded_integer<0u, 100u>; - - constexpr auto v10 = verified_bounded_t{bounded_t{u8{10}}}; - constexpr auto v20 = verified_bounded_t{bounded_t{u8{20}}}; - constexpr auto v5 = verified_bounded_t{bounded_t{u8{5}}}; - constexpr auto v7 = verified_bounded_t{bounded_t{u8{7}}}; - constexpr auto v17 = verified_bounded_t{bounded_t{u8{17}}}; - - const auto b3 = bounded_t{u8{3}}; - const auto b5 = bounded_t{u8{5}}; - const auto b7 = bounded_t{u8{7}}; - const auto b10 = bounded_t{u8{10}}; - - // verified + basis -> basis - BOOST_TEST((v10 + b7) == bounded_t{u8{17}}); - - // basis + verified -> basis - BOOST_TEST((b10 + v7) == bounded_t{u8{17}}); - - // verified - basis -> basis - BOOST_TEST((v20 - b7) == bounded_t{u8{13}}); - - // basis - verified -> basis - BOOST_TEST((b10 - v5) == bounded_t{u8{5}}); - - // verified * basis -> basis - BOOST_TEST((v5 * b3) == bounded_t{u8{15}}); - - // basis * verified -> basis - BOOST_TEST((b3 * v5) == bounded_t{u8{15}}); - - // verified / basis -> basis - BOOST_TEST((v20 / b5) == bounded_t{u8{4}}); - - // basis / verified -> basis - BOOST_TEST((b10 / v5) == bounded_t{u8{2}}); - - // verified % basis -> basis - BOOST_TEST((v17 % b5) == bounded_t{u8{2}}); - - // basis % verified -> basis - BOOST_TEST((b10 % v5) == bounded_t{u8{0}}); -} - -void test_bounded_mixed_comparisons() -{ - using bounded_t = bounded_uint<0u, 100u>; - using verified_bounded_t = verified_bounded_integer<0u, 100u>; - - constexpr auto v10 = verified_bounded_t{bounded_t{u8{10}}}; - constexpr auto v20 = verified_bounded_t{bounded_t{u8{20}}}; - - const auto b10 = bounded_t{u8{10}}; - const auto b20 = bounded_t{u8{20}}; - - // verified == basis - BOOST_TEST(v10 == b10); - BOOST_TEST(!(v10 == b20)); - - // basis == verified - BOOST_TEST(b10 == v10); - BOOST_TEST(!(b20 == v10)); - - // verified != basis - BOOST_TEST(v10 != b20); - BOOST_TEST(!(v10 != b10)); - - // verified < basis - BOOST_TEST(v10 < b20); - BOOST_TEST(!(v20 < b10)); - - // verified > basis - BOOST_TEST(v20 > b10); - BOOST_TEST(!(v10 > b20)); - - // verified <=> basis - BOOST_TEST((v10 <=> b10) == std::strong_ordering::equal); - BOOST_TEST((v10 <=> b20) == std::strong_ordering::less); - BOOST_TEST((v20 <=> b10) == std::strong_ordering::greater); - - // basis <=> verified - BOOST_TEST((b10 <=> v10) == std::strong_ordering::equal); - BOOST_TEST((b10 <=> v20) == std::strong_ordering::less); - BOOST_TEST((b20 <=> v10) == std::strong_ordering::greater); -} - -void test_bounded_asymmetric_operands() -{ - using bounded_t = bounded_uint<0u, 100u>; - using verified_bounded_t = verified_bounded_integer<0u, 100u>; - - constexpr auto v30 = verified_bounded_t{bounded_t{u8{30}}}; - constexpr auto v7 = verified_bounded_t{bounded_t{u8{7}}}; - - const auto b10 = bounded_t{u8{10}}; - - // verified - basis: 30 - 10 = 20 - BOOST_TEST((v30 - b10) == bounded_t{u8{20}}); - - // basis - verified: 10 - 7 = 3 - BOOST_TEST((b10 - v7) == bounded_t{u8{3}}); - - // verified / basis: 30 / 10 = 3 - BOOST_TEST((v30 / b10) == bounded_t{u8{3}}); - - // basis / verified: 10 / 7 = 1 - BOOST_TEST((b10 / v7) == bounded_t{u8{1}}); - - // verified % basis: 30 % 10 = 0 - BOOST_TEST((v30 % b10) == bounded_t{u8{0}}); - - // basis % verified: 10 % 7 = 3 - BOOST_TEST((b10 % v7) == bounded_t{u8{3}}); -} - -// ============================================================================= -// Wider bounded range tests (u16, u32 basis) -// ============================================================================= - -void test_bounded_u16_mixed_ops() -{ - using bounded_t = bounded_uint<0u, 1000u>; - using verified_bounded_t = verified_bounded_integer<0u, 1000u>; - - constexpr auto v100 = verified_bounded_t{bounded_t{u16{100}}}; - constexpr auto v200 = verified_bounded_t{bounded_t{u16{200}}}; - - const auto b50 = bounded_t{u16{50}}; - const auto b100 = bounded_t{u16{100}}; - - // Arithmetic - BOOST_TEST((v100 + b50) == bounded_t{u16{150}}); - BOOST_TEST((b50 + v100) == bounded_t{u16{150}}); - BOOST_TEST((v200 - b50) == bounded_t{u16{150}}); - BOOST_TEST((b100 - v100) == bounded_t{u16{0}}); - BOOST_TEST((v200 / b100) == bounded_t{u16{2}}); - BOOST_TEST((b100 % v200) == bounded_t{u16{100}}); - - // Comparisons - BOOST_TEST(v100 == b100); - BOOST_TEST(v100 < bounded_t{u16{200}}); - BOOST_TEST((v200 <=> b100) == std::strong_ordering::greater); -} - -void test_bounded_u32_mixed_ops() -{ - using bounded_t = bounded_uint<0u, 100000u>; - using verified_bounded_t = verified_bounded_integer<0u, 100000u>; - - constexpr auto v1000 = verified_bounded_t{bounded_t{u32{1000}}}; - constexpr auto v5000 = verified_bounded_t{bounded_t{u32{5000}}}; - - const auto b500 = bounded_t{u32{500}}; - const auto b1000 = bounded_t{u32{1000}}; - - // Arithmetic - BOOST_TEST((v1000 + b500) == bounded_t{u32{1500}}); - BOOST_TEST((b500 + v1000) == bounded_t{u32{1500}}); - BOOST_TEST((v5000 - b500) == bounded_t{u32{4500}}); - BOOST_TEST((v5000 / b1000) == bounded_t{u32{5}}); - BOOST_TEST((b1000 / v5000) == bounded_t{u32{0}}); - - // Comparisons - BOOST_TEST(v1000 == b1000); - BOOST_TEST(v5000 > b1000); - BOOST_TEST(b500 < v1000); -} - -// ============================================================================= -// Constexpr mixed operations -// ============================================================================= - -template -void test_constexpr_mixed_ops() -{ - constexpr auto v10 = VerifiedT{BasisT{10}}; - constexpr auto b5 = BasisT{5}; - - // constexpr arithmetic - constexpr auto sum = v10 + b5; - constexpr auto diff = v10 - b5; - constexpr auto prod = v10 * b5; - constexpr auto quot = v10 / b5; - constexpr auto mod = v10 % b5; - - static_assert(sum == BasisT{15}); - static_assert(diff == BasisT{5}); - static_assert(prod == BasisT{50}); - static_assert(quot == BasisT{2}); - static_assert(mod == BasisT{0}); - - // constexpr comparisons - static_assert(v10 == BasisT{10}); - static_assert(v10 != BasisT{5}); - static_assert(v10 > BasisT{5}); - static_assert(v10 < BasisT{20}); - static_assert((v10 <=> BasisT{10}) == std::strong_ordering::equal); -} - -// ============================================================================= -// Edge case: zero operations -// ============================================================================= - -template -void test_zero_operations() -{ - constexpr auto v0 = VerifiedT{BasisT{0}}; - constexpr auto v42 = VerifiedT{BasisT{42}}; - constexpr auto v1 = VerifiedT{BasisT{1}}; - - const auto b0 = BasisT{0}; - const auto b1 = BasisT{1}; - const auto b42 = BasisT{42}; - - // Adding zero - BOOST_TEST((v42 + b0) == BasisT{42}); - BOOST_TEST((b0 + v42) == BasisT{42}); - BOOST_TEST((v0 + b42) == BasisT{42}); - BOOST_TEST((b42 + v0) == BasisT{42}); - - // Subtracting zero - BOOST_TEST((v42 - b0) == BasisT{42}); - BOOST_TEST((b42 - v0) == BasisT{42}); - - // Multiplying by zero - BOOST_TEST((v42 * b0) == BasisT{0}); - BOOST_TEST((b0 * v42) == BasisT{0}); - - // Multiplying by one - BOOST_TEST((v42 * b1) == BasisT{42}); - BOOST_TEST((b42 * v1) == BasisT{42}); -} - -// ============================================================================= -// Edge case: max value comparisons -// ============================================================================= - -template -void test_max_value_comparisons() -{ - using underlying = detail::underlying_type_t; - - constexpr auto v_max = VerifiedT{BasisT{std::numeric_limits::max()}}; - constexpr auto v0 = VerifiedT{BasisT{0}}; - - const auto b_max = BasisT{std::numeric_limits::max()}; - const auto b0 = BasisT{0}; - - BOOST_TEST(v_max == b_max); - BOOST_TEST(v0 == b0); - BOOST_TEST(v_max > b0); - BOOST_TEST(v0 < b_max); - BOOST_TEST(b_max == v_max); - BOOST_TEST(b0 < v_max); -} - -// ============================================================================= -// Mixed bitwise ops: verified_uN with uN -// ============================================================================= - -template -void test_mixed_bitwise() -{ - constexpr auto v_ff = VerifiedT{BasisT{0xFF}}; - constexpr auto v_0f = VerifiedT{BasisT{0x0F}}; - constexpr auto v_1 = VerifiedT{BasisT{1}}; - constexpr auto v_8 = VerifiedT{BasisT{8}}; - - const auto b_f0 = BasisT{0xF0}; - const auto b_0f = BasisT{0x0F}; - const auto b_3 = BasisT{3}; - - // verified & basis - BOOST_TEST((v_ff & b_0f) == BasisT{0x0F}); - BOOST_TEST((v_0f & b_f0) == BasisT{0x00}); - - // basis & verified - BOOST_TEST((b_f0 & v_0f) == BasisT{0x00}); - BOOST_TEST((b_0f & v_ff) == BasisT{0x0F}); - - // verified | basis - BOOST_TEST((v_0f | b_f0) == BasisT{0xFF}); - - // basis | verified - BOOST_TEST((b_f0 | v_0f) == BasisT{0xFF}); - - // verified ^ basis - BOOST_TEST((v_ff ^ b_0f) == BasisT{0xF0}); - - // basis ^ verified - BOOST_TEST((b_0f ^ v_ff) == BasisT{0xF0}); - - // verified << basis - BOOST_TEST((v_1 << b_3) == BasisT{8}); - - // basis << verified - BOOST_TEST((BasisT{1} << v_1) == BasisT{2}); - - // verified >> basis - BOOST_TEST((v_8 >> b_3) == BasisT{1}); - - // basis >> verified - BOOST_TEST((BasisT{8} >> v_1) == BasisT{4}); -} - -// ============================================================================= -// Main -// ============================================================================= - -int main() -{ - // --- Mixed arithmetic: verified op basis --- - test_verified_op_basis_arithmetic(); - test_verified_op_basis_arithmetic(); - test_verified_op_basis_arithmetic(); - test_verified_op_basis_arithmetic(); - test_verified_op_basis_arithmetic(); - - // --- Mixed arithmetic: basis op verified --- - test_basis_op_verified_arithmetic(); - test_basis_op_verified_arithmetic(); - test_basis_op_verified_arithmetic(); - test_basis_op_verified_arithmetic(); - test_basis_op_verified_arithmetic(); - - // --- Asymmetric operand tests --- - test_asymmetric_operands(); - test_asymmetric_operands(); - test_asymmetric_operands(); - test_asymmetric_operands(); - test_asymmetric_operands(); - - // --- Mixed comparisons --- - test_mixed_comparisons(); - test_mixed_comparisons(); - test_mixed_comparisons(); - test_mixed_comparisons(); - test_mixed_comparisons(); - - // --- Constexpr mixed ops --- - test_constexpr_mixed_ops(); - test_constexpr_mixed_ops(); - test_constexpr_mixed_ops(); - test_constexpr_mixed_ops(); - test_constexpr_mixed_ops(); - - // --- Zero operations --- - test_zero_operations(); - test_zero_operations(); - test_zero_operations(); - test_zero_operations(); - test_zero_operations(); - - // --- Max value comparisons --- - test_max_value_comparisons(); - test_max_value_comparisons(); - test_max_value_comparisons(); - test_max_value_comparisons(); - test_max_value_comparisons(); - - // --- Bounded integer mixed ops --- - test_bounded_mixed_arithmetic(); - test_bounded_mixed_comparisons(); - test_bounded_asymmetric_operands(); - test_bounded_u16_mixed_ops(); - test_bounded_u32_mixed_ops(); - - // --- Mixed bitwise --- - test_mixed_bitwise(); - test_mixed_bitwise(); - test_mixed_bitwise(); - test_mixed_bitwise(); - test_mixed_bitwise(); - - return boost::report_errors(); -} diff --git a/test/test_verified_std_format.cpp b/test/test_verified_std_format.cpp deleted file mode 100644 index a7683dd..0000000 --- a/test/test_verified_std_format.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifdef BOOST_SAFE_NUMBERS_BUILD_MODULE - -import boost.safe_numbers; - -#else - -#include - -#ifdef BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_FORMAT - -#include - -#endif - -#endif - -#ifdef BOOST_SAFE_NUMBERS_DETAIL_INT128_HAS_FORMAT - -#include - -using namespace boost::safe_numbers; - -template -void test() -{ - constexpr auto x = VerifiedT{BasisT{42}}; - - BOOST_TEST_CSTR_EQ(std::format("{}", x).c_str(), "42"); - BOOST_TEST_CSTR_EQ(std::format("{:08x}", x).c_str(), "0000002a"); - BOOST_TEST_CSTR_EQ(std::format("{:#010b}", x).c_str(), "0b00101010"); -} - -template -void test_zero() -{ - constexpr auto x = VerifiedT{BasisT{0}}; - - BOOST_TEST_CSTR_EQ(std::format("{}", x).c_str(), "0"); -} - -template -void test_255() -{ - constexpr auto x = VerifiedT{BasisT{255}}; - - BOOST_TEST_CSTR_EQ(std::format("{}", x).c_str(), "255"); - BOOST_TEST_CSTR_EQ(std::format("{:x}", x).c_str(), "ff"); -} - -int main() -{ - test(); - test(); - test(); - test(); - test(); - - test_zero(); - test_zero(); - test_zero(); - test_zero(); - test_zero(); - - test_255(); - test_255(); - test_255(); - test_255(); - test_255(); - - // Bounded verified type - using test_bounded = bounded_uint<0u, 255u>; - using test_verified_bounded = verified_bounded_integer<0u, 255u>; - - test(); - test_zero(); - test_255(); - - return boost::report_errors(); -} - -#else - -int main() -{ - return 0; -} - -#endif diff --git a/test/test_verified_streaming.cpp b/test/test_verified_streaming.cpp deleted file mode 100644 index a518990..0000000 --- a/test/test_verified_streaming.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include -#include -#include - -using namespace boost::safe_numbers; - -// Verified types are consteval for construction, so only output streaming -// (operator<<) is testable. Input streaming (operator>>) would require -// runtime construction which is not possible with consteval constructors. - -template -void test_output() -{ - constexpr auto val = VerifiedT{BasisT{42}}; - - std::stringstream out; - out << val; - - BOOST_TEST_CSTR_EQ(out.str().c_str(), "42"); -} - -template -void test_output_zero() -{ - constexpr auto val = VerifiedT{BasisT{0}}; - - std::stringstream out; - out << val; - - BOOST_TEST_CSTR_EQ(out.str().c_str(), "0"); -} - -template -void test_output_large() -{ - constexpr auto val = VerifiedT{BasisT{255}}; - - std::stringstream out; - out << val; - - BOOST_TEST_CSTR_EQ(out.str().c_str(), "255"); -} - -int main() -{ - test_output(); - test_output(); - test_output(); - test_output(); - test_output(); - - test_output_zero(); - test_output_zero(); - test_output_zero(); - test_output_zero(); - test_output_zero(); - - test_output_large(); - test_output_large(); - test_output_large(); - test_output_large(); - test_output_large(); - - // Bounded verified type - using test_bounded = bounded_uint<0u, 255u>; - using test_verified_bounded = verified_bounded_integer<0u, 255u>; - - test_output(); - test_output_zero(); - test_output_large(); - - return boost::report_errors(); -} From 5d056a9307c5c8a1ed5d5bdc5bb54c5b42da9c48 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 24 Feb 2026 10:09:06 -0500 Subject: [PATCH 4/5] Remove examples of verified types --- examples/byte_conversions.cpp | 41 +------- examples/compile_fail_verified_overflow.cpp | 21 ---- examples/verified_arithmetic.cpp | 72 ------------- examples/verified_construction.cpp | 66 ------------ examples/verified_mixed_ops.cpp | 71 ------------- examples/verified_runtime_usage.cpp | 106 -------------------- 6 files changed, 1 insertion(+), 376 deletions(-) delete mode 100644 examples/compile_fail_verified_overflow.cpp delete mode 100644 examples/verified_arithmetic.cpp delete mode 100644 examples/verified_construction.cpp delete mode 100644 examples/verified_mixed_ops.cpp delete mode 100644 examples/verified_runtime_usage.cpp diff --git a/examples/byte_conversions.cpp b/examples/byte_conversions.cpp index 125af6d..60427a9 100644 --- a/examples/byte_conversions.cpp +++ b/examples/byte_conversions.cpp @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #include -#include +#include #include #include #include @@ -112,44 +112,5 @@ int main() << static_cast(le[0]) << '\n'; } - // ---- Verified types (compile-time) ---- - std::cout << "\n=== Verified types (compile-time) ===\n"; - { - constexpr auto bytes = to_be_bytes(verified_u32{u32{0x01020304U}}); - static_assert(bytes[0] == std::byte{0x01}); - static_assert(bytes[3] == std::byte{0x04}); - std::cout << "verified_u32 to_be_bytes: "; - for (const auto& b : bytes) - { - std::cout << std::hex << std::setfill('0') << std::setw(2) - << static_cast(b) << ' '; - } - std::cout << '\n'; - } - { - constexpr auto original = verified_u32{u32{0xDEADBEEFU}}; - constexpr auto bytes = to_be_bytes(original); - constexpr auto reconstructed = from_be_bytes(std::span{bytes}); - static_assert(reconstructed == original); - std::cout << "verified_u32 BE round-trip: 0x" << std::hex - << static_cast(static_cast(reconstructed)) << '\n'; - } - { - constexpr auto original = verified_u64{u64{0x0123456789ABCDEFULL}}; - constexpr auto bytes = to_le_bytes(original); - constexpr auto reconstructed = from_le_bytes(std::span{bytes}); - static_assert(reconstructed == original); - std::cout << "verified_u64 LE round-trip: 0x" << std::hex - << static_cast(static_cast(reconstructed)) << '\n'; - } - { - constexpr auto original = verified_u32{u32{0xCAFEBABEU}}; - constexpr auto bytes = to_ne_bytes(original); - constexpr auto reconstructed = from_ne_bytes(std::span{bytes}); - static_assert(reconstructed == original); - std::cout << "verified_u32 NE round-trip: 0x" << std::hex - << static_cast(static_cast(reconstructed)) << '\n'; - } - return 0; } diff --git a/examples/compile_fail_verified_overflow.cpp b/examples/compile_fail_verified_overflow.cpp deleted file mode 100644 index 996876b..0000000 --- a/examples/compile_fail_verified_overflow.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt -// -// This example demonstrates that verified types catch overflow at compile time. -// This file is expected to fail compilation. - -#include - -int main() -{ - using namespace boost::safe_numbers; - - // u8 can hold 0-255. Adding 1 to 255 overflows. - // With a verified type this is a compile error, not a runtime exception. - constexpr auto result {verified_u8{u8{255}} + verified_u8{u8{1}}}; - - static_cast(result); - - return 0; -} diff --git a/examples/verified_arithmetic.cpp b/examples/verified_arithmetic.cpp deleted file mode 100644 index ea8fa9b..0000000 --- a/examples/verified_arithmetic.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt -// -// Verified types enforce that all arithmetic is evaluated at compile time. -// If an operation would overflow, it produces a compile error instead of -// a runtime exception. - -#include -#include -#include - -int main() -{ - using namespace boost::safe_numbers; - - // All arithmetic is consteval - evaluated entirely by the compiler. - // The results are compile-time constants that cannot be modified at runtime. - - // Basic arithmetic - constexpr auto sum {verified_u32{100U} + verified_u32{200U}}; - constexpr auto diff {verified_u32{200U} - verified_u32{100U}}; - constexpr auto prod {verified_u32{15U} * verified_u32{20U}}; - constexpr auto quot {verified_u32{300U} / verified_u32{10U}}; - constexpr auto rem {verified_u32{17U} % verified_u32{5U}}; - - std::cout << "100 + 200 = " << sum << '\n'; - std::cout << "200 - 100 = " << diff << '\n'; - std::cout << "15 * 20 = " << prod << '\n'; - std::cout << "300 / 10 = " << quot << '\n'; - std::cout << "17 % 5 = " << rem << '\n'; - - std::cout << '\n'; - - // Compound assignment and increment/decrement are also consteval. - // They work inside consteval contexts like consteval functions: - constexpr auto incremented = []() consteval { - auto val = verified_u8{u8{10}}; - ++val; - return val; - }(); - std::cout << "10 after ++: " << incremented << '\n'; - - constexpr auto accumulated = []() consteval { - auto val = verified_u16{u16{0}}; - val += verified_u16{u16{100}}; - val += verified_u16{u16{200}}; - val += verified_u16{u16{300}}; - return val; - }(); - std::cout << "0 + 100 + 200 + 300 = " << accumulated << '\n'; - - std::cout << '\n'; - - // Overflow is caught at compile time. - // These would produce compile errors: - // - // constexpr auto overflow {verified_u8{u8{255}} + verified_u8{u8{1}}}; - // error: consteval call to overflow-checking addition fails - // - // constexpr auto underflow {verified_u8{u8{0}} - verified_u8{u8{1}}}; - // error: consteval call to overflow-checking subtraction fails - - // Bounded arithmetic is also compile-time checked - constexpr auto bounded_sum { - verified_bounded_integer<0u, 1000u>{500u} + - verified_bounded_integer<0u, 1000u>{400u} - }; - std::cout << "bounded 500 + 400 = " << bounded_sum << '\n'; - - return 0; -} diff --git a/examples/verified_construction.cpp b/examples/verified_construction.cpp deleted file mode 100644 index ed30d3f..0000000 --- a/examples/verified_construction.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt -// -// Verified types guarantee that all values are validated at compile time. -// Construction and arithmetic are consteval (compile-time only), -// while conversions and comparisons are constexpr (usable at runtime). - -#include -#include -#include -#include - -int main() -{ - using namespace boost::safe_numbers; - - // Construction must happen at compile time. - // All of these are evaluated by the compiler: - constexpr verified_u8 a {u8{42}}; - constexpr verified_u16 b {u16{1000}}; - constexpr verified_u32 c {u32{100000}}; - constexpr verified_u64 d {u64{9999999999ULL}}; - - // You can also construct from the underlying fundamental type directly - constexpr verified_u32 e {42U}; - - // At runtime, verified types are read-only values. - // Output works because operator<< uses the constexpr conversion operator: - std::cout << "verified_u8: " << a << '\n'; - std::cout << "verified_u16: " << b << '\n'; - std::cout << "verified_u32: " << c << '\n'; - std::cout << "verified_u64: " << d << '\n'; - std::cout << "verified_u32: " << e << '\n'; - - std::cout << '\n'; - - // Explicit conversion back to fundamental types works at runtime - const auto raw = static_cast(c); - std::cout << "Converted to uint32_t: " << raw << '\n'; - - // Comparisons work at runtime (same-type only) - constexpr verified_u32 f {u32{50000}}; - if (e < f) - { - std::cout << "42 < 50000: true\n"; - } - - // The three-way comparison operator is also available - if ((e <=> e) == std::strong_ordering::equal) - { - std::cout << "42 == 42: true\n"; - } - - std::cout << '\n'; - - // Bounded verified types work the same way. - // The bounded range is enforced at compile time: - constexpr verified_bounded_integer<0u, 100u> percent {50u}; - std::cout << "percent: " << percent << '\n'; - - // This would be a compile error - value out of bounds: - // constexpr verified_bounded_integer<0u, 100u> bad {101u}; - - return 0; -} diff --git a/examples/verified_mixed_ops.cpp b/examples/verified_mixed_ops.cpp deleted file mode 100644 index 8c3dedb..0000000 --- a/examples/verified_mixed_ops.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt -// -// Verified types are compile-time constants, but they can participate in -// runtime operations when mixed with their basis types. The result is -// always the runtime (basis) type, effectively treating the verified value -// as a read-only constant operand. - -#include -#include -#include - -int main() -{ - using namespace boost::safe_numbers; - - // A compile-time constant and a runtime value - constexpr auto tax_rate = verified_u32{u32{20}}; - auto price = u32{500}; - - // --- Arithmetic: verified op basis -> basis --- - const auto tax = tax_rate * price / u32{100}; - std::cout << "Tax on " << price << " at " << tax_rate << "%: " << tax << '\n'; - - // --- Arithmetic: basis op verified -> basis --- - constexpr auto discount = verified_u32{u32{50}}; - const auto discounted = price - discount; - std::cout << price << " - " << discount << " discount = " << discounted << '\n'; - - std::cout << '\n'; - - // --- Comparisons: verified vs basis --- - constexpr auto threshold = verified_u32{u32{1000}}; - std::cout << std::boolalpha; - std::cout << price << " < " << threshold << ": " << (price < threshold) << '\n'; - std::cout << threshold << " > " << price << ": " << (threshold > price) << '\n'; - std::cout << price << " == " << threshold << ": " << (price == threshold) << '\n'; - - std::cout << '\n'; - - // --- Bitwise operations: verified vs basis --- - constexpr auto mask = verified_u32{u32{0xFF}}; - auto value = u32{0xABCD}; - const auto masked = value & mask; - std::cout << "0xABCD & 0xFF = " << masked << '\n'; - - const auto combined = mask | value; - std::cout << "0xFF | 0xABCD = " << combined << '\n'; - - // Shift operations - constexpr auto shift = verified_u32{u32{4}}; - const auto shifted = value << shift; - std::cout << "0xABCD << 4 = " << shifted << '\n'; - - std::cout << '\n'; - - // --- Bounded types work too --- - constexpr auto bounded_offset = verified_bounded_integer<0u, 100u>{10u}; - auto bounded_val = bounded_uint<0u, 100u>{50u}; - const auto bounded_sum = bounded_val + bounded_offset; - std::cout << "bounded 50 + 10 = " << bounded_sum << '\n'; - - const auto bounded_diff = bounded_val - bounded_offset; - std::cout << "bounded 50 - 10 = " << bounded_diff << '\n'; - - // Bounded comparisons - std::cout << "bounded 50 > 10: " << (bounded_val > bounded_offset) << '\n'; - - return 0; -} diff --git a/examples/verified_runtime_usage.cpp b/examples/verified_runtime_usage.cpp deleted file mode 100644 index 6fdc47c..0000000 --- a/examples/verified_runtime_usage.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2026 Matt Borland -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt -// -// This example shows what you can do with verified types at runtime. -// While construction and arithmetic are compile-time only, verified types -// are designed to be useful runtime constants: they support output streaming, -// to_chars, std::format/fmt::format, comparisons, and bit queries. - -#include -#include -#include -#include -#include -#include -#include - -int main() -{ - using namespace boost::safe_numbers; - - constexpr verified_u32 val {1024U}; - - // --- Output streaming (runtime) --- - std::cout << "Value: " << val << '\n'; - - // --- Conversions (runtime) --- - // Explicit cast back to the fundamental type - const auto raw = static_cast(val); - std::cout << "As uint32_t: " << raw << '\n'; - - // Explicit cast to the safe basis type - const auto basis = static_cast(val); - std::cout << "As u32: " << basis << '\n'; - - std::cout << '\n'; - - // --- Comparisons (runtime) --- - constexpr verified_u32 small {10U}; - constexpr verified_u32 large {50000U}; - - std::cout << std::boolalpha; - std::cout << "10 == 10: " << (small == small) << '\n'; - std::cout << "10 != 50000: " << (small != large) << '\n'; - std::cout << "10 < 50000: " << (small < large) << '\n'; - std::cout << "10 >= 50000: " << (small >= large) << '\n'; - - std::cout << '\n'; - - // --- to_chars (runtime) --- - // Writing to a character buffer works at runtime since it only - // reads the value through the constexpr conversion operator - char buffer[32]; - auto result = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val); - if (result) - { - *result.ptr = '\0'; - std::cout << "to_chars (base 10): " << buffer << '\n'; - } - - result = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), val, 16); - if (result) - { - *result.ptr = '\0'; - std::cout << "to_chars (base 16): " << buffer << '\n'; - } - - std::cout << '\n'; - - // --- Bit queries (runtime) --- - // Functions returning int or bool work at runtime - std::cout << "has_single_bit(1024) = " << has_single_bit(val) << '\n'; - std::cout << "bit_width(1024) = " << bit_width(val) << '\n'; - std::cout << "countl_zero(1024) = " << countl_zero(val) << '\n'; - std::cout << "popcount(1024) = " << popcount(val) << '\n'; - - // Functions returning the verified type are consteval. - // They work as compile-time constants: - constexpr auto ceiled = bit_ceil(verified_u32{48U}); - constexpr auto floored = bit_floor(verified_u32{48U}); - std::cout << "bit_ceil(48) = " << ceiled << '\n'; - std::cout << "bit_floor(48) = " << floored << '\n'; - - std::cout << '\n'; - - // --- std::numeric_limits (runtime) --- - std::cout << "numeric_limits::min() = " - << std::numeric_limits::min() << '\n'; - std::cout << "numeric_limits::max() = " - << std::numeric_limits::max() << '\n'; - std::cout << "numeric_limits::digits = " - << std::numeric_limits::digits << '\n'; - - // --- What does NOT work at runtime --- - // The following operations require compile-time evaluation: - // - // verified_u32 x {some_runtime_variable}; // ERROR: consteval constructor - // auto sum = a + b; // Only at compile time, e.g. constexpr auto sum = a + b; - // from_chars(str, str + len, verified_val); // consteval only - // bit_ceil(verified_val); // consteval only (returns verified type) - // - // This is by design: verified types are compile-time validated constants - // that can be safely passed around and inspected at runtime. - - return 0; -} From dd6cafc59752a49ddeaa7762e05a3b4460587754 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Tue, 24 Feb 2026 10:09:17 -0500 Subject: [PATCH 5/5] Remove documentation of verified types --- doc/modules/ROOT/nav.adoc | 5 - doc/modules/ROOT/pages/api_reference.adoc | 28 -- doc/modules/ROOT/pages/bit.adoc | 25 -- doc/modules/ROOT/pages/byte_conversions.adoc | 255 +------------- doc/modules/ROOT/pages/charconv.adoc | 22 -- doc/modules/ROOT/pages/examples.adoc | 151 --------- doc/modules/ROOT/pages/format.adoc | 5 - doc/modules/ROOT/pages/integer_utilities.adoc | 221 +------------ doc/modules/ROOT/pages/iostream.adoc | 17 - doc/modules/ROOT/pages/limits.adoc | 31 -- doc/modules/ROOT/pages/numeric.adoc | 79 +---- doc/modules/ROOT/pages/pretty_printers.adoc | 35 -- doc/modules/ROOT/pages/verified_integers.adoc | 312 ------------------ 13 files changed, 3 insertions(+), 1183 deletions(-) delete mode 100644 doc/modules/ROOT/pages/verified_integers.adoc diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index d98d40d..31bda6a 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -14,10 +14,6 @@ ** xref:examples.adoc#examples_fmt_format[Formatting] ** xref:examples.adoc#examples_iostream[Stream I/O] ** xref:examples.adoc#examples_bit[Bit Manipulation] -** xref:examples.adoc#examples_verified_construction[Verified Types: Construction] -** xref:examples.adoc#examples_verified_arithmetic[Verified Types: Arithmetic] -** xref:examples.adoc#examples_verified_runtime[Verified Types: Runtime Capabilities] -** xref:examples.adoc#examples_verified_compile_fail[Verified Types: Compile-Time Overflow] * xref:pretty_printers.adoc[] * xref:api_reference.adoc[] ** xref:api_reference.adoc#api_namespaces[Namespaces] @@ -27,7 +23,6 @@ * xref:policies.adoc[] * xref:unsigned_integers.adoc[] * xref:bounded_uint.adoc[] -* xref:verified_integers.adoc[] * xref:literals.adoc[] * xref:limits.adoc[] * xref:format.adoc[] diff --git a/doc/modules/ROOT/pages/api_reference.adoc b/doc/modules/ROOT/pages/api_reference.adoc index a157293..e0bae32 100644 --- a/doc/modules/ROOT/pages/api_reference.adoc +++ b/doc/modules/ROOT/pages/api_reference.adoc @@ -53,31 +53,6 @@ https://www.boost.org/LICENSE_1_0.txt | Safe unsigned integer constrained to a compile-time range `[Min, Max]` |=== -=== Verified Integer Types - -[cols="1,2", options="header"] -|=== -| Type | Description - -| xref:verified_integers.adoc[`verified_u8`] -| Compile-time verified safe unsigned 8-bit integer - -| xref:verified_integers.adoc[`verified_u16`] -| Compile-time verified safe unsigned 16-bit integer - -| xref:verified_integers.adoc[`verified_u32`] -| Compile-time verified safe unsigned 32-bit integer - -| xref:verified_integers.adoc[`verified_u64`] -| Compile-time verified safe unsigned 64-bit integer - -| xref:verified_integers.adoc[`verified_u128`] -| Compile-time verified safe unsigned 128-bit integer - -| xref:verified_integers.adoc[`verified_bounded_integer`] -| Compile-time verified bounded unsigned integer constrained to `[Min, Max]` -|=== - === Enumerations [cols="1,2", options="header"] @@ -346,7 +321,4 @@ This header is not included in the convenience header since it requires external | `` | Byte order conversion functions (`to_be`, `from_be`, `to_le`, `from_le`, `to_be_bytes`, `from_be_bytes`, `to_le_bytes`, `from_le_bytes`, `to_ne_bytes`, `from_ne_bytes`) - -| `` -| Verified integer types (`verified_u8`, `verified_u16`, `verified_u32`, `verified_u64`, `verified_u128`, `verified_bounded_integer`) |=== diff --git a/doc/modules/ROOT/pages/bit.adoc b/doc/modules/ROOT/pages/bit.adoc index 12dfd54..d1295ad 100644 --- a/doc/modules/ROOT/pages/bit.adoc +++ b/doc/modules/ROOT/pages/bit.adoc @@ -183,31 +183,6 @@ Implemented using a lookup-table approach that reverses each byte individually a NOTE: `bitswap` is not available for `bounded_uint` types. Bit reversal can produce values outside the valid bounded range, making the operation semantically meaningless for bounded integers. -== Verified Types - -The bit functions have special behavior with xref:verified_integers.adoc[verified types]: - -Functions that return `int` or `bool` (`has_single_bit`, `bit_width`, `countl_zero`, `countl_one`, `countr_zero`, `countr_one`, `popcount`) work at runtime with verified types. -These functions only read the value via the `constexpr` conversion operator. - -Functions that return the safe type (`bit_ceil`, `bit_floor`, `rotl`, `rotr`, `byteswap`, `bitswap`) have `consteval` overloads for verified types, meaning they can only be called at compile time. -The `consteval` overloads use a `requires` clause to distinguish them: - -[source,c++] ----- -// Runtime overload (non-verified types) -template - requires (!is_verified_type_v) -constexpr auto bit_ceil(UnsignedInt x) noexcept -> UnsignedInt; - -// Compile-time overload (verified types only) -template - requires is_verified_type_v -consteval auto bit_ceil(UnsignedInt x) noexcept -> UnsignedInt; ----- - -The same pattern applies to `bit_floor`, `rotl`, `rotr`, `byteswap`, and `bitswap`. - == Examples .This https://github.com/boostorg/safe_numbers/blob/develop/examples/bit.cpp[example] demonstrates the bit manipulation functions. diff --git a/doc/modules/ROOT/pages/byte_conversions.adoc b/doc/modules/ROOT/pages/byte_conversions.adoc index 3c7b754..e615eba 100644 --- a/doc/modules/ROOT/pages/byte_conversions.adoc +++ b/doc/modules/ROOT/pages/byte_conversions.adoc @@ -11,7 +11,7 @@ https://www.boost.org/LICENSE_1_0.txt == Description The library provides functions for converting safe integer types to and from big-endian or little-endian byte order. -These operate on the non-bounded unsigned types (`u8`, `u16`, `u32`, `u64`, `u128`) and their verified counterparts. +These operate on the non-bounded unsigned types (`u8`, `u16`, `u32`, `u64`, `u128`). For big-endian conversions (`to_be`/`from_be`): on big-endian platforms these are no-ops; on little-endian platforms they delegate to `byteswap`. @@ -26,12 +26,9 @@ For little-endian conversions (`to_le`/`from_le`): on little-endian platforms th Converts a value from the native byte order to big-endian byte order. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto to_be(const T value) noexcept -> T; ---- @@ -59,27 +56,6 @@ auto be_val = to_be(u32{0x01020304}); // On big-endian: be_val == u32{0x01020304} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto to_be(const verified_type_basis value) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. - -Since `to_be` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto be_val = to_be(verified_u32{u32{0x01020304}}); ----- - == from_be Converts a value from big-endian byte order to the native byte order. @@ -87,12 +63,9 @@ Converts a value from big-endian byte order to the native byte order. This is the inverse of `to_be`. Since byte swapping is its own inverse, `from_be` delegates directly to `to_be`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto from_be(const T value) noexcept -> T; ---- @@ -119,39 +92,13 @@ auto native_val = from_be(to_be(u64{0x0123456789ABCDEF})); // native_val == u64{0x0123456789ABCDEF} (round-trip) ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto from_be(const verified_type_basis value) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. - -Since `from_be` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto val = verified_u32{u32{0xDEADBEEF}}; -constexpr auto round_tripped = from_be(to_be(val)); -static_assert(round_tripped == val); ----- - == to_le Converts a value from the native byte order to little-endian byte order. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto to_le(const T value) noexcept -> T; ---- @@ -179,27 +126,6 @@ auto le_val = to_le(u32{0x01020304}); // On big-endian: le_val == u32{0x04030201} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto to_le(const verified_type_basis value) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. - -Since `to_le` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto le_val = to_le(verified_u32{u32{0x01020304}}); ----- - == from_le Converts a value from little-endian byte order to the native byte order. @@ -207,12 +133,9 @@ Converts a value from little-endian byte order to the native byte order. This is the inverse of `to_le`. Since byte swapping is its own inverse, `from_le` delegates directly to `to_le`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto from_le(const T value) noexcept -> T; ---- @@ -239,40 +162,14 @@ auto native_val = from_le(to_le(u64{0x0123456789ABCDEF})); // native_val == u64{0x0123456789ABCDEF} (round-trip) ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto from_le(const verified_type_basis value) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. - -Since `from_le` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto val = verified_u32{u32{0xDEADBEEF}}; -constexpr auto round_tripped = from_le(to_le(val)); -static_assert(round_tripped == val); ----- - == to_be_bytes Converts a safe integer value to a big-endian byte array. The value is first converted to big-endian byte order using `to_be`, then reinterpreted as an array of `std::byte`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto to_be_bytes(const T value) noexcept -> std::array; ---- @@ -298,37 +195,14 @@ auto bytes = to_be_bytes(u32{0x01020304}); // bytes == {0x01, 0x02, 0x03, 0x04} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto to_be_bytes(const verified_type_basis value) noexcept -> std::array; ----- - -Compile-time only overload for verified types. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto bytes = to_be_bytes(verified_u32{u32{0x01020304}}); -// bytes == {0x01, 0x02, 0x03, 0x04} ----- - == from_be_bytes Reconstructs a safe integer value from a big-endian byte array. The bytes are reinterpreted as the underlying type and then converted from big-endian to native byte order using `from_be`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto from_be_bytes(const std::span bytes) -> T; ---- @@ -369,44 +243,14 @@ auto reconstructed = from_be_bytes(std::span{to_be_byte // reconstructed == original ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto from_be_bytes(const std::span bytes) -> T; ----- - -Compile-time only overload for verified types. -The span must have a fixed extent matching `sizeof(T)`; a mismatched extent produces a `static_assert` failure. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr std::array bytes {std::byte{0x01}, std::byte{0x02}, std::byte{0x03}, std::byte{0x04}}; -constexpr auto val = from_be_bytes(std::span{bytes}); -// val == verified_u32{u32{0x01020304}} - -// Round-trip -constexpr auto original = verified_u32{u32{0xDEADBEEF}}; -constexpr auto reconstructed = from_be_bytes(std::span{to_be_bytes(original)}); -static_assert(reconstructed == original); ----- - == to_le_bytes Converts a safe integer value to a little-endian byte array. The value is first converted to little-endian byte order using `to_le`, then reinterpreted as an array of `std::byte`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto to_le_bytes(const T value) noexcept -> std::array; ---- @@ -432,37 +276,14 @@ auto bytes = to_le_bytes(u32{0x01020304}); // bytes == {0x04, 0x03, 0x02, 0x01} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto to_le_bytes(const verified_type_basis value) noexcept -> std::array; ----- - -Compile-time only overload for verified types. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto bytes = to_le_bytes(verified_u32{u32{0x01020304}}); -// bytes == {0x04, 0x03, 0x02, 0x01} ----- - == from_le_bytes Reconstructs a safe integer value from a little-endian byte array. The bytes are reinterpreted as the underlying type and then converted from little-endian to native byte order using `from_le`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto from_le_bytes(const std::span bytes) -> T; ---- @@ -503,33 +324,6 @@ auto reconstructed = from_le_bytes(std::span{to_le_byte // reconstructed == original ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto from_le_bytes(const std::span bytes) -> T; ----- - -Compile-time only overload for verified types. -The span must have a fixed extent matching `sizeof(T)`; a mismatched extent produces a `static_assert` failure. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr std::array bytes {std::byte{0x04}, std::byte{0x03}, std::byte{0x02}, std::byte{0x01}}; -constexpr auto val = from_le_bytes(std::span{bytes}); -// val == verified_u32{u32{0x01020304}} - -// Round-trip -constexpr auto original = verified_u32{u32{0xDEADBEEF}}; -constexpr auto reconstructed = from_le_bytes(std::span{to_le_bytes(original)}); -static_assert(reconstructed == original); ----- - == to_ne_bytes Converts a safe integer value to a native-endian byte array. @@ -537,12 +331,9 @@ Delegates to `to_le_bytes` on little-endian platforms and `to_be_bytes` on big-e The result is equivalent to `std::bit_cast>(value)` -- i.e., the raw in-memory representation. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto to_ne_bytes(const T value) noexcept -> std::array; ---- @@ -569,36 +360,14 @@ auto bytes = to_ne_bytes(u32{0x01020304}); // On big-endian: bytes == {0x01, 0x02, 0x03, 0x04} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto to_ne_bytes(const verified_type_basis value) noexcept -> std::array; ----- - -Compile-time only overload for verified types. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto bytes = to_ne_bytes(verified_u32{u32{0x01020304}}); ----- - == from_ne_bytes Reconstructs a safe integer value from a native-endian byte array. Delegates to `from_le_bytes` on little-endian platforms and `from_be_bytes` on big-endian platforms. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto from_ne_bytes(const std::span bytes) -> T; ---- @@ -634,28 +403,6 @@ auto reconstructed = from_ne_bytes(std::span{to_ne_byte // reconstructed == original ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto from_ne_bytes(const std::span bytes) -> T; ----- - -Compile-time only overload for verified types. -The span must have a fixed extent matching `sizeof(T)`; a mismatched extent produces a `static_assert` failure. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto original = verified_u32{u32{0xDEADBEEF}}; -constexpr auto reconstructed = from_ne_bytes(std::span{to_ne_bytes(original)}); -static_assert(reconstructed == original); ----- - == Example For a complete example demonstrating all byte conversion functions, see xref:examples.adoc#examples_byte_conversions[Byte Conversions]. diff --git a/doc/modules/ROOT/pages/charconv.adoc b/doc/modules/ROOT/pages/charconv.adoc index 50ca1b1..599b073 100644 --- a/doc/modules/ROOT/pages/charconv.adoc +++ b/doc/modules/ROOT/pages/charconv.adoc @@ -158,28 +158,6 @@ Returns `boost::charconv::from_chars_result` with: - `ptr` pointing to the first character not matching the pattern - `ec` set to `std::errc{}` on success, `std::errc::invalid_argument` if no valid conversion, or `std::errc::result_out_of_range` if the value overflows -== Verified Types - -`to_chars` works at runtime with xref:verified_integers.adoc[verified types] since it only reads the value. - -`from_chars` has a `consteval` overload for verified types -- it can only be used at compile time. -The two overloads are distinguished via a `requires` clause: - -[source,c++] ----- -// Runtime overload (non-verified types) -template - requires (!safe_numbers::detail::is_verified_type_v) -constexpr auto from_chars(const char* first, const char* last, - T& value, int base = 10) -> charconv::from_chars_result; - -// Compile-time overload (verified types only) -template - requires safe_numbers::detail::is_verified_type_v -consteval auto from_chars(const char* first, const char* last, - T& value, int base = 10) -> charconv::from_chars_result; ----- - == Examples .This https://github.com/boostorg/safe_numbers/blob/develop/examples/charconv.cpp[example] demonstrates how to use `to_chars` and `from_chars` with safe integer types. diff --git a/doc/modules/ROOT/pages/examples.adoc b/doc/modules/ROOT/pages/examples.adoc index 302ca13..8b13db7 100644 --- a/doc/modules/ROOT/pages/examples.adoc +++ b/doc/modules/ROOT/pages/examples.adoc @@ -386,7 +386,6 @@ shr(u32(8), 1) = 4 == Byte Conversions The library provides functions for converting safe integers to and from byte arrays in big-endian, little-endian, or native byte order. -Verified types support the same conversions at compile time via `consteval` overloads. .This https://github.com/boostorg/safe_numbers/blob/develop/examples/byte_conversions.cpp[example] demonstrates byte conversion functions with all safe integer types. ==== @@ -418,12 +417,6 @@ Round-trip: -> u32: 0xdeadbeef === u8 round-trip === u8(0x42) -> BE: 42 u8(0x42) -> LE: 42 - -=== Verified types (compile-time) === -verified_u32 to_be_bytes: 01 02 03 04 -verified_u32 BE round-trip: 0xdeadbeef -verified_u64 LE round-trip: 0x123456789abcdef -verified_u32 NE round-trip: 0xcafebabe ---- ==== @@ -467,147 +460,3 @@ std::max(u16(100), u16(200)) = 200 std::clamp(u64(500), u64(0), u64(100)) = 100 ---- ==== - -[#examples_verified_construction] -== Verified Types: Construction and Runtime Usage - -Verified types use `consteval` constructors and arithmetic, guaranteeing that all values are validated at compile time. -At runtime, verified types are read-only constants that support output streaming, explicit conversions, and comparisons. - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/verified_construction.cpp[example] demonstrates construction and runtime use of verified types. -==== -[source, c++] ----- -include::example$verified_construction.cpp[] ----- - -Output: ----- -verified_u8: 42 -verified_u16: 1000 -verified_u32: 100000 -verified_u64: 9999999999 -verified_u32: 42 - -Converted to uint32_t: 100000 -42 < 50000: true -42 == 42: true - -percent: 50 ----- -==== - -[#examples_verified_arithmetic] -== Verified Types: Compile-Time Arithmetic - -All arithmetic on verified types (`+`, `-`, `*`, `/`, `%`, `+=`, `++`, etc.) is `consteval` -- evaluated entirely by the compiler. -If an operation overflows, it produces a compile error instead of a runtime exception. - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/verified_arithmetic.cpp[example] demonstrates compile-time arithmetic with verified types. -==== -[source, c++] ----- -include::example$verified_arithmetic.cpp[] ----- - -Output: ----- -100 + 200 = 300 -200 - 100 = 100 -15 * 20 = 300 -300 / 10 = 30 -17 % 5 = 2 - -10 after ++: 11 -0 + 100 + 200 + 300 = 600 - -bounded 500 + 400 = 900 ----- -==== - -[#examples_verified_runtime] -== Verified Types: Runtime Capabilities - -While construction and arithmetic are compile-time only, verified types support a wide range of runtime operations: -output streaming, explicit conversions, comparisons, `to_chars`, bit queries, and `std::numeric_limits`. - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/verified_runtime_usage.cpp[example] shows what verified types can do at runtime. -==== -[source, c++] ----- -include::example$verified_runtime_usage.cpp[] ----- - -Output: ----- -Value: 1024 -As uint32_t: 1024 -As u32: 1024 - -10 == 10: true -10 != 50000: true -10 < 50000: true -10 >= 50000: false - -to_chars (base 10): 1024 -to_chars (base 16): 400 - -has_single_bit(1024) = true -bit_width(1024) = 11 -countl_zero(1024) = 21 -popcount(1024) = 1 -bit_ceil(48) = 64 -bit_floor(48) = 32 - -numeric_limits::min() = 0 -numeric_limits::max() = 255 -numeric_limits::digits = 32 ----- -==== - -[#examples_verified_mixed_ops] -== Verified Types: Mixed-Type Operations - -Verified types are compile-time constants, but they can participate in runtime expressions when mixed with their basis types. -The result is always the runtime (basis) type, treating the verified value as a read-only constant operand. -Arithmetic, comparisons, and bitwise operations are all supported. - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/verified_mixed_ops.cpp[example] demonstrates mixed-type operations between verified constants and runtime values. -==== -[source, c++] ----- -include::example$verified_mixed_ops.cpp[] ----- - -Output: ----- -Tax on 500 at 20%: 100 -500 - 50 discount = 450 - -500 < 1000: true -1000 > 500: true -500 == 1000: false - -0xABCD & 0xFF = 205 -0xFF | 0xABCD = 44031 -0xABCD << 4 = 703696 - -bounded 50 + 10 = 60 -bounded 50 - 10 = 40 -bounded 50 > 10: true ----- -==== - -[#examples_verified_compile_fail] -== Verified Types: Compile-Time Overflow Detection - -Verified types catch overflow at compile time. -Attempting to overflow a verified type produces a compiler error rather than a runtime exception. - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/compile_fail_verified_overflow.cpp[example] fails to compile because `u8(255) + u8(1)` overflows. -==== -[source, c++] ----- -include::example$compile_fail_verified_overflow.cpp[] ----- -==== diff --git a/doc/modules/ROOT/pages/format.adoc b/doc/modules/ROOT/pages/format.adoc index c44703b..1b8253f 100644 --- a/doc/modules/ROOT/pages/format.adoc +++ b/doc/modules/ROOT/pages/format.adoc @@ -124,11 +124,6 @@ The full format specifier order is: {[fill][align][sign][#][0][width][.precision][L][type]} ---- -== Verified Types - -Formatting works with xref:verified_integers.adoc[verified types] through the `library_type` concept. -Both `std::format` and `pass:[{fmt}]` work at runtime via the `constexpr` conversion operator, since the formatter only reads the value. - == Examples IMPORTANT: The header `` is *NOT* part of the convenience header, because it is an optional dependency on a potentially compiled library. diff --git a/doc/modules/ROOT/pages/integer_utilities.adoc b/doc/modules/ROOT/pages/integer_utilities.adoc index e0fbded..fa17ade 100644 --- a/doc/modules/ROOT/pages/integer_utilities.adoc +++ b/doc/modules/ROOT/pages/integer_utilities.adoc @@ -11,7 +11,7 @@ https://www.boost.org/LICENSE_1_0.txt == Description The library provides utility functions for safe integer types. -These operate on the non-bounded unsigned types (`u8`, `u16`, `u32`, `u64`, `u128`) and their verified counterparts. +These operate on the non-bounded unsigned types (`u8`, `u16`, `u32`, `u64`, `u128`). [source,c++] ---- @@ -20,12 +20,9 @@ These operate on the non-bounded unsigned types (`u8`, `u16`, `u32`, `u64`, `u12 == isqrt -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto isqrt(const T val) -> T; ---- @@ -58,29 +55,6 @@ auto t = isqrt(u32{0}); // t == u32{0} auto u = isqrt(u32{1}); // u == u32{1} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto isqrt(const verified_type_basis val) -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Delegates to the runtime overload after extracting the basis value, and wraps the result back into a verified type. - -Since `isqrt` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = isqrt(verified_u32{u32{144}}); // r == verified_u32{u32{12}} -constexpr auto s = isqrt(verified_u64{u64{1000000}}); // s == verified_u64{u64{1000}} ----- - == remove_trailing_zeros Removes trailing decimal zeros from an unsigned integer value using a branchless algorithm based on modular multiplicative inverses (Granlund-Montgomery division). @@ -97,12 +71,9 @@ struct remove_trailing_zeros_return }; ---- -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto remove_trailing_zeros(const T n); ---- @@ -166,39 +137,13 @@ auto r3 = remove_trailing_zeros(u8{static_cast(7)}); // r3.trimmed_number == 7, r3.number_of_removed_zeros == 0 ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto remove_trailing_zeros(const verified_type_basis val); ----- - -Compile-time-only overload for verified types. -Delegates to the detail implementation after extracting the underlying value. - -Since `remove_trailing_zeros` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = remove_trailing_zeros(verified_u32{u32{5000}}); -// r.trimmed_number == 5, r.number_of_removed_zeros == 3 ----- - == is_power_10 Tests whether an unsigned integer value is an exact power of 10 (i.e., one of 1, 10, 100, 1000, ...). -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto is_power_10(const T n) -> bool; ---- @@ -222,38 +167,13 @@ is_power_10(u32{1234}); // false is_power_10(u64{10000000000000000000ULL}); // true ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto is_power_10(const verified_type_basis n) -> bool; ----- - -Compile-time-only overload for verified types. - -Since `is_power_10` is `consteval` for verified types, the result is guaranteed to be a compile-time constant and can be used directly in `static_assert`. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(is_power_10(verified_u32{u32{100}})); -static_assert(!is_power_10(verified_u32{u32{200}})); ----- - == log2 Returns the integer base-2 logarithm (floor of log~2~) of a value. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto log2(const T n) noexcept -> int; ---- @@ -284,40 +204,15 @@ auto r3 = log2(u32{1}); // r3 == 0 auto r4 = log2(u64{9223372036854775808ULL}); // r4 == 63 (2^63) ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto log2(const verified_type_basis n) noexcept -> int; ----- - -Compile-time only overload for verified types. - -Since `log2` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(log2(verified_u32{u32{1048576}}) == 20); // 2^20 -static_assert(log2(verified_u64{u64{9223372036854775808ULL}}) == 63); ----- - == log10 Returns the integer base-10 logarithm (floor of log~10~) of a value. Uses an O(1) algorithm based on the most significant bit position to approximate `log~10~`, refined with a single power-of-10 table lookup. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto log10(const T n) noexcept -> int; ---- @@ -343,38 +238,13 @@ auto r3 = log10(u32{1}); // r3 == 0 auto r4 = log10(u64{10000000000000000000ULL}); // r4 == 19 ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto log10(const verified_type_basis n) noexcept -> int; ----- - -Compile-time only overload for verified types. - -Since `log10` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(log10(verified_u32{u32{1000000000}}) == 9); -static_assert(log10(verified_u64{u64{10000000000000000000ULL}}) == 19); ----- - == ipow Integer exponentiation using the exponentiation-by-squaring algorithm. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto ipow(const T a, const T b) noexcept -> T; ---- @@ -413,39 +283,13 @@ auto r3 = ipow(u64{3}, u64{30}); // r3 == u64{205891132094649} auto r4 = ipow(u32{5}, u32{0}); // r4 == u32{1} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto ipow(const verified_type_basis a, const verified_type_basis b) -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Returns a verified type, preserving the compile-time guarantee. - -Since `ipow` is `consteval` for verified types, the computation is guaranteed to occur at compile time. Overflow produces a compile error. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = ipow(verified_u32{u32{2}}, verified_u32{u32{20}}); // r == verified_u32{u32{1048576}} -constexpr auto s = ipow(verified_u64{u64{10}}, verified_u64{u64{18}}); // s == verified_u64{u64{1000000000000000000}} ----- - == is_power_2 Tests whether an unsigned integer value is an exact power of 2 (i.e., has exactly one bit set). -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto is_power_2(const T n) noexcept -> bool; ---- @@ -469,35 +313,11 @@ is_power_2(u32{1000}); // false is_power_2(u64{9223372036854775808ULL}); // true (2^63) ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto is_power_2(const verified_type_basis n) noexcept -> bool; ----- - -Compile-time-only overload for verified types. - -Since `is_power_2` is `consteval` for verified types, the result is guaranteed to be a compile-time constant and can be used directly in `static_assert`. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(is_power_2(verified_u32{u32{1048576}})); // 2^20 -static_assert(!is_power_2(verified_u32{u32{1000000}})); ----- - == abs_diff Computes the absolute difference between two integers without risk of underflow. For unsigned types, naive subtraction `a - b` when `b > a` would underflow; `abs_diff` always returns the non-negative distance between the two values. -=== Runtime Overload - [source,c++] ---- template @@ -534,31 +354,14 @@ auto r3 = abs_diff(u32{42}, u32{42}); // r3 == u32{0} auto r4 = abs_diff(u32{0}, u32{100}); // r4 == u32{100} ---- -=== Verified Types - -Since `abs_diff` uses comparison and subtraction operators, it works with verified types at compile time via the `consteval` operators on verified types. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(abs_diff(verified_u32{u32{100}}, verified_u32{u32{200}}) == verified_u32{u32{100}}); -static_assert(abs_diff(verified_u64{u64{1000}}, verified_u64{u64{3000}}) == verified_u64{u64{2000}}); ----- - == div_ceil Computes the ceiling of integer division, i.e., the smallest integer not less than the exact quotient `a / b`. For unsigned types, this is equivalent to `(a + b - 1) / b` but computed without risk of overflow. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto div_ceil(const T a, const T b) noexcept -> T; ---- @@ -594,25 +397,3 @@ auto r4 = div_ceil(u32{1}, u32{2}); // r4 == u32{1} (ceil(0.5) = 1) auto r5 = div_ceil(u32{100}, u32{100}); // r5 == u32{1} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto div_ceil(const verified_type_basis a, const verified_type_basis b) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Delegates to the runtime overload after extracting the basis value, and wraps the result back into a verified type. - -Since `div_ceil` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -static_assert(div_ceil(verified_u32{u32{10}}, verified_u32{u32{3}}) == verified_u32{u32{4}}); -static_assert(div_ceil(verified_u64{u64{1000}}, verified_u64{u64{3}}) == verified_u64{u64{334}}); ----- diff --git a/doc/modules/ROOT/pages/iostream.adoc b/doc/modules/ROOT/pages/iostream.adoc index 9a62a0f..0a566a8 100644 --- a/doc/modules/ROOT/pages/iostream.adoc +++ b/doc/modules/ROOT/pages/iostream.adoc @@ -72,23 +72,6 @@ Standard stream manipulators (`std::hex`, `std::oct`, `std::dec`, `std::setw`, e For `u8`, the input is read as a `std::uint32_t` to avoid character interpretation, then narrowed to `std::uint8_t`. -== Verified Types - -`operator>>` is not available for xref:verified_integers.adoc[verified types]. -The overload is excluded via a `requires` clause: - -[source,c++] ----- -template - requires (!is_verified_type_v) -auto operator>>(std::basic_istream& is, LibType& v) - -> std::basic_istream&; ----- - -This is by design: verified types can only be constructed at compile time, so reading a value from a stream into a verified type is not meaningful. - -`operator<<` works normally with verified types via their `constexpr` conversion operator, since output only reads the value. - == Examples .This https://github.com/boostorg/safe_numbers/blob/develop/examples/iostream.cpp[example] demonstrates stream I/O with safe integer types. diff --git a/doc/modules/ROOT/pages/limits.adoc b/doc/modules/ROOT/pages/limits.adoc index ff9312e..fe9aa3a 100644 --- a/doc/modules/ROOT/pages/limits.adoc +++ b/doc/modules/ROOT/pages/limits.adoc @@ -239,37 +239,6 @@ class numeric_limits> NOTE: The non-applicable member functions (`epsilon`, `round_error`, `infinity`, `quiet_NaN`, `signaling_NaN`, `denorm_min`) return `min()` rather than a zero-constructed value, since zero may fall outside the valid range for types with a non-zero lower bound. -== Verified Integer Specialization - -A partial specialization of `std::numeric_limits` is provided for all `verified_type_basis` types, including both `verified_u8`-`verified_u128` and `verified_bounded_integer`. - -[source,c++] ----- -namespace std { - -template -class numeric_limits> -{ - using type = boost::safe_numbers::detail::verified_type_basis; - using basis_limits = std::numeric_limits; - - // Static member constants delegate to std::numeric_limits - // ... - - static constexpr type min(); - static constexpr type max(); - static constexpr type lowest(); - // ... remaining functions delegate to basis_limits -}; - -} // namespace std ----- - -Static properties and functions delegate to `std::numeric_limits` (the safe integer basis type, not the underlying fundamental type). -This means verified bounded types correctly report their bounded `min()` and `max()` values. - -The `static constexpr` member functions work because constructing the verified type with a constant expression invokes the `consteval` constructor as an immediate invocation, which is permitted in a `constexpr` context. - === Example .This https://github.com/boostorg/safe_numbers/blob/develop/examples/bounded_limits.cpp[example] demonstrates `std::numeric_limits` with bounded integer types. diff --git a/doc/modules/ROOT/pages/numeric.adoc b/doc/modules/ROOT/pages/numeric.adoc index 8472040..224ea81 100644 --- a/doc/modules/ROOT/pages/numeric.adoc +++ b/doc/modules/ROOT/pages/numeric.adoc @@ -11,7 +11,7 @@ https://www.boost.org/LICENSE_1_0.txt == Description The library provides overloads of standard `` algorithms for safe integer types. -These operate on the non-bounded types (`u8`, `u16`, `u32`, `u64`, `u128`) and their verified counterparts. +These operate on the non-bounded types (`u8`, `u16`, `u32`, `u64`, `u128`). [source,c++] ---- @@ -22,12 +22,9 @@ These operate on the non-bounded types (`u8`, `u16`, `u32`, `u64`, `u128`) and t Computes the greatest common divisor of two integers using the Euclidean algorithm. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto gcd(const T m, const T n) noexcept -> T; ---- @@ -61,39 +58,13 @@ auto r4 = gcd(u32{7}, u32{11}); // r4 == u32{1} (coprime) auto r5 = gcd(u32{0}, u32{42}); // r5 == u32{42} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto gcd(const verified_type_basis m, const verified_type_basis n) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Delegates to the same underlying algorithm after extracting the basis value, and wraps the result back into a verified type. - -Since `gcd` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = gcd(verified_u32{u32{1234567890}}, verified_u32{u32{987654321}}); // r == verified_u32{u32{9}} -static_assert(gcd(verified_u64{u64{1000000000000}}, verified_u64{u64{750000000000}}) == verified_u64{u64{250000000000}}); ----- - == lcm Computes the least common multiple of two integers. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto lcm(const T m, const T n) noexcept -> T; ---- @@ -127,40 +98,14 @@ auto r4 = lcm(u32{7}, u32{11}); // r4 == u32{77} (coprime) auto r5 = lcm(u32{0}, u32{42}); // r5 == u32{0} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto lcm(const verified_type_basis m, const verified_type_basis n) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Delegates to the same underlying algorithm after extracting the basis value, and wraps the result back into a verified type. - -Since `lcm` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = lcm(verified_u32{u32{12}}, verified_u32{u32{18}}); // r == verified_u32{u32{36}} -static_assert(lcm(verified_u64{u64{1000}}, verified_u64{u64{750}}) == verified_u64{u64{3000}}); ----- - == midpoint Computes the midpoint of two integers without overflow. The result is rounded towards the first argument `a`. -=== Runtime Overload - [source,c++] ---- template - requires (!is_verified_type_v) constexpr auto midpoint(const T a, const T b) noexcept -> T; ---- @@ -194,25 +139,3 @@ auto r4 = midpoint(u32{0}, u32{0}); // r4 == u32{0} auto r5 = midpoint(u32{3}, u32{3}); // r5 == u32{3} ---- -=== Verified Overload - -[source,c++] ----- -template -consteval auto midpoint(const verified_type_basis a, const verified_type_basis b) noexcept -> verified_type_basis; ----- - -Compile-time only overload for verified types. -Delegates to the same underlying algorithm after extracting the basis value, and wraps the result back into a verified type. - -Since `midpoint` is `consteval` for verified types, the result is guaranteed to be a compile-time constant. - -==== Example - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto r = midpoint(verified_u32{u32{0}}, verified_u32{u32{10}}); // r == verified_u32{u32{5}} -static_assert(midpoint(verified_u64{u64{100}}, verified_u64{u64{200}}) == verified_u64{u64{150}}); ----- diff --git a/doc/modules/ROOT/pages/pretty_printers.adoc b/doc/modules/ROOT/pages/pretty_printers.adoc index 1b9108b..ae4a0ba 100644 --- a/doc/modules/ROOT/pages/pretty_printers.adoc +++ b/doc/modules/ROOT/pages/pretty_printers.adoc @@ -83,38 +83,3 @@ percentage = [0, 100] 42 port = [1, 65535] 8,080 ---- -=== Verified Unsigned Integers (`verified_u8`, `verified_u16`, `verified_u32`, `verified_u64`, `verified_u128`) - -Verified unsigned integer types display identically to their underlying type as comma-separated decimal values. - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto rate = verified_u32{u32{20}}; -constexpr auto limit = verified_u64{u64{1'000'000}}; ----- - -Debugger output: - ----- -rate = 20 -limit = 1,000,000 ----- - -=== Verified Bounded Integers (`verified_bounded_integer`) - -Verified bounded integers display identically to `bounded_uint` -- showing the compile-time bounds and the current value in the format `[Min, Max] Current`: - -[source,c++] ----- -using namespace boost::safe_numbers; - -constexpr auto offset = verified_bounded_integer<0u, 100u>{10u}; ----- - -Debugger output: - ----- -offset = [0, 100] 10 ----- diff --git a/doc/modules/ROOT/pages/verified_integers.adoc b/doc/modules/ROOT/pages/verified_integers.adoc deleted file mode 100644 index 4d70e20..0000000 --- a/doc/modules/ROOT/pages/verified_integers.adoc +++ /dev/null @@ -1,312 +0,0 @@ -//// -Copyright 2026 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#verified_integers] - -= Verified Integer Types - -== Description - -The library provides verified integer types that guarantee compile-time validation via `consteval` constructors and arithmetic. -All values must be known at compile time -- at runtime, verified types are read-only constants. -They wrap any `library_type` (both `u8`-`u128` and `bounded_uint`), adding a layer of compile-time-only enforcement on top of the existing safety guarantees. - -|=== -| Type | Basis Type | Underlying Type - -| `verified_u8` | `u8` | `std::uint8_t` -| `verified_u16` | `u16` | `std::uint16_t` -| `verified_u32` | `u32` | `std::uint32_t` -| `verified_u64` | `u64` | `std::uint64_t` -| `verified_u128` | `u128` | `uint128_t` -| `verified_bounded_integer` | `bounded_uint` | smallest unsigned type fitting `Max` -|=== - -Each type exposes an `underlying_type` member type alias that refers to the underlying fundamental integer type. - -[source,c++] ----- -#include - -namespace boost::safe_numbers { - -using verified_u8 = detail::verified_type_basis; -using verified_u16 = detail::verified_type_basis; -using verified_u32 = detail::verified_type_basis; -using verified_u64 = detail::verified_type_basis; -using verified_u128 = detail::verified_type_basis; - -template -using verified_bounded_integer = detail::verified_type_basis>; - -template -class verified_type_basis { - -public: - using underlying_type = underlying_type_t; - - // Construction (consteval -- compile-time only) - consteval verified_type_basis() = default; // zero-initializes - explicit consteval verified_type_basis(const BasisType basis); - explicit consteval verified_type_basis(const underlying_type val); - - // Conversion to basis type and underlying type (constexpr -- works at runtime) - explicit constexpr operator BasisType() const noexcept; - explicit constexpr operator underlying_type() const noexcept; - - // Comparison operators (constexpr -- works at runtime) - friend constexpr auto operator<=>(verified_type_basis lhs, verified_type_basis rhs) noexcept - -> std::strong_ordering = default; - - // Compound assignment operators (consteval -- compile-time only) - consteval auto operator+=(verified_type_basis rhs) -> verified_type_basis&; - consteval auto operator-=(verified_type_basis rhs) -> verified_type_basis&; - consteval auto operator*=(verified_type_basis rhs) -> verified_type_basis&; - consteval auto operator/=(verified_type_basis rhs) -> verified_type_basis&; - consteval auto operator%=(verified_type_basis rhs) -> verified_type_basis&; - - // Increment and decrement operators (consteval -- compile-time only) - consteval auto operator++() -> verified_type_basis&; - consteval auto operator++(int) -> verified_type_basis; - consteval auto operator--() -> verified_type_basis&; - consteval auto operator--(int) -> verified_type_basis; - -}; // class verified_type_basis - -// Arithmetic operators (consteval -- compile-time only, overflow = compile error) -template -consteval auto operator+(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator-(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator*(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator/(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator%(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -} // namespace boost::safe_numbers ----- - -== Operator Behavior - -=== Construction - -[source,c++] ----- -consteval verified_type_basis() = default; -explicit consteval verified_type_basis(const BasisType basis); -explicit consteval verified_type_basis(const underlying_type val); ----- - -Construction is `consteval` -- it can only occur at compile time. -The default constructor zero-initializes the value, consistent with the behavior of the basis types. -The second overload accepts the safe integer basis type directly; the third accepts the underlying fundamental type and constructs the basis type internally. -If the value is out of range (e.g., for a bounded type), the compilation fails. - -=== Conversion - -[source,c++] ----- -explicit constexpr operator BasisType() const noexcept; -explicit constexpr operator underlying_type() const noexcept; ----- - -Conversion to the basis type or the underlying fundamental type is `constexpr` and explicit. -These work at runtime, allowing verified values to be used in runtime contexts such as stream output, `to_chars`, and comparisons. - -=== Comparison Operators - -[source,c++] ----- -friend constexpr auto operator<=>(verified_type_basis lhs, verified_type_basis rhs) noexcept - -> std::strong_ordering = default; ----- - -Full three-way comparison is supported via `pass:[operator<=>]`, which returns `std::strong_ordering`. -All comparison operators (`<`, `<=`, `>`, `>=`, `==`, `!=`) are available. -Comparisons are `constexpr` and work at runtime. - -=== Arithmetic Operators - -[source,c++] ----- -template -consteval auto operator+(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator-(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator*(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator/(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; - -template -consteval auto operator%(const verified_type_basis lhs, - const verified_type_basis rhs) -> verified_type_basis; ----- - -All arithmetic operators are `consteval` -- they can only be evaluated at compile time. -The operations delegate to the underlying basis type's operators, which perform overflow/underflow checking. -If an overflow, underflow, or division-by-zero would occur, the compilation fails with a compiler error. - -=== Compound Assignment Operators - -[source,c++] ----- -consteval auto operator+=(verified_type_basis rhs) -> verified_type_basis&; -consteval auto operator-=(verified_type_basis rhs) -> verified_type_basis&; -consteval auto operator*=(verified_type_basis rhs) -> verified_type_basis&; -consteval auto operator/=(verified_type_basis rhs) -> verified_type_basis&; -consteval auto operator%=(verified_type_basis rhs) -> verified_type_basis&; ----- - -Compound assignment operators are `consteval` and delegate to the corresponding arithmetic operators. -Overflow at compile time produces a compiler error. - -=== Increment and Decrement Operators - -[source,c++] ----- -consteval auto operator++() -> verified_type_basis&; -consteval auto operator++(int) -> verified_type_basis; -consteval auto operator--() -> verified_type_basis&; -consteval auto operator--(int) -> verified_type_basis; ----- - -- `++` (pre/post): `consteval`. Produces a compile error if the value is already at the maximum. -- `--` (pre/post): `consteval`. Produces a compile error if the value is already at the minimum (zero for unbounded types, `Min` for bounded types). - -== Compile-Time vs Runtime - -|=== -| Operation | Qualifier | Compile-Time | Runtime - -| Default construction | `consteval` | Yes | No -| Explicit construction | `consteval` | Yes | No -| Arithmetic (`+`, `-`, `*`, `/`, `%`) | `consteval` | Yes | No -| Compound assignment (`+=`, `-=`, etc.) | `consteval` | Yes | No -| Increment/decrement (`++`, `--`) | `consteval` | Yes | No -| Conversion to `BasisType` / `underlying_type` | `constexpr` | Yes | Yes -| Comparison (`<=>`, `==`, `<`, etc.) | `constexpr` | Yes | Yes -| Mixed-type arithmetic (verified op basis) | `constexpr` | Yes | Yes -| Mixed-type comparison (verified vs basis) | `constexpr` | Yes | Yes -| Mixed-type bitwise (verified op basis) | `constexpr` | Yes | Yes -|=== - -== Mixed-Type Operations - -Verified types can participate in runtime expressions when combined with their basis types. -The result is always the runtime (basis) type, effectively treating the verified value as a read-only constant operand. - -=== Arithmetic - -[source,c++] ----- -// verified op basis -> basis -template -constexpr auto operator+(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> VerifiedBasisType; - -// basis op verified -> basis -template -constexpr auto operator+(const VerifiedBasisType lhs, - const verified_type_basis rhs) -> VerifiedBasisType; ----- - -All five arithmetic operators (`+`, `-`, `*`, `/`, `%`) are supported in both directions. -Cross-width operations (e.g., `verified_u32 + u64`) are allowed and follow the same rules as the basis types. - -=== Comparisons - -[source,c++] ----- -template -constexpr auto operator<=>(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> std::strong_ordering; - -template -constexpr auto operator==(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> bool; ----- - -Full three-way and equality comparisons are supported in both directions (verified vs basis, basis vs verified). - -=== Bitwise Operations - -[source,c++] ----- -template -constexpr auto operator&(const verified_type_basis lhs, - const VerifiedBasisType rhs) -> VerifiedBasisType; ----- - -Bitwise operators (`&`, `|`, `^`, `<<`, `>>`) are supported for non-bounded unsigned types in both directions. -Shift operators include overflow checking via `throw_exception` policy. - -=== Type Safety - -Mixed operations between verified types with *different* basis types produce clear `static_assert` errors: - -[source,c++] ----- -constexpr auto a = verified_u32{u32{10}}; -constexpr auto b = verified_u64{u64{20}}; - -auto c = a + b; // error: "Can not perform addition between verified types with different basis types" -auto d = (a == b); // error: "Can not compare verified types with different basis types" ----- - -.This https://github.com/boostorg/safe_numbers/blob/develop/examples/verified_mixed_ops.cpp[example] demonstrates mixed-type operations between verified constants and runtime values. -==== -[source, c++] ----- -include::example$verified_mixed_ops.cpp[] ----- - -Output: ----- -Tax on 500 at 20%: 100 -500 - 50 discount = 450 - -500 < 1000: true -1000 > 500: true -500 == 1000: false - -0xABCD & 0xFF = 205 -0xFF | 0xABCD = 44031 -0xABCD << 4 = 703696 - -bounded 50 + 10 = 60 -bounded 50 - 10 = 40 -bounded 50 > 10: true ----- -==== - -== Integration with Other Features - -Verified types integrate with the library's other features: - -- **xref:bit.adoc[]**: Functions returning `int` or `bool` (`has_single_bit`, `bit_width`, `countl_zero`, `countl_one`, `countr_zero`, `countr_one`, `popcount`) work at runtime with verified types via their `constexpr` conversion operator. Functions returning the safe type (`bit_ceil`, `bit_floor`, `rotl`, `rotr`, `byteswap`) have `consteval` overloads for verified types. -- **xref:charconv.adoc[]**: `to_chars` works at runtime (only reads the value). `from_chars` has a `consteval` overload for verified types. -- **xref:iostream.adoc[]**: `operator<<` works normally at runtime. `operator>>` is excluded for verified types since they cannot be constructed at runtime. -- **xref:limits.adoc[]**: `std::numeric_limits` is fully specialized for all verified types, delegating to the basis type's limits. For verified bounded types, `min()` and `max()` correctly report the bounded range. -- **xref:format.adoc[]**: Both `std::format` and `pass:[{fmt}]` work at runtime via the `constexpr` conversion operator.