From 3840a6d170d7c6fa1afb8542d06fca3d97ff6491 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 15 Feb 2026 17:39:21 -0500 Subject: [PATCH] Correct clamping when converting to a type with a wider range. --- ClockReceiver/ClockReceiver.hpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ClockReceiver/ClockReceiver.hpp b/ClockReceiver/ClockReceiver.hpp index 08d394b2f..b0e28a448 100644 --- a/ClockReceiver/ClockReceiver.hpp +++ b/ClockReceiver/ClockReceiver.hpp @@ -134,9 +134,9 @@ public: // bool operator () is not supported because it offers an implicit cast to int, // which is prone silently to permit misuse. - /// @returns The underlying int, converted to an integral type of your choosing, clamped to that int's range. - template forceinline constexpr Type as() const { - if constexpr (sizeof(Type) == sizeof(IntType)) { + /// @returns The underlying int, converted to a numeric type of your choosing, clamped to that type's range. + template constexpr Type as() const { + if constexpr (sizeof(Type) == sizeof(IntType) && std::is_integral_v) { if constexpr (std::is_same_v) { return length_; } else if constexpr (std::is_signed_v) { @@ -150,12 +150,7 @@ public: } } - const auto clamped = std::clamp( - length_, - IntType(std::numeric_limits::min()), - IntType(std::numeric_limits::max()) - ); - return Type(clamped); + return Type(std::clamp(length_, low, high)); } /// @returns The underlying int, in its native form. @@ -188,6 +183,22 @@ public: protected: IntType length_; + +private: + template + static consteval bool can_represent(const Type x) { + return std::numeric_limits::min() <= x && std::numeric_limits::max() >= x; + } + + template + static constexpr IntType low = + can_represent(std::numeric_limits::min()) ? + IntType(std::numeric_limits::min()) : std::numeric_limits::min(); + + template + static constexpr IntType high = + can_represent(std::numeric_limits::max()) ? + IntType(std::numeric_limits::max()) : std::numeric_limits::max(); }; /// Describes an integer number of whole cycles: pairs of clock signal transitions.