There is not a one-time solution, but a solution that is suitable for many use cases, is to use a double based on duration to check the range. Maybe something like:
#include <chrono> #include <iostream> #include <stdexcept> template <class Duration, class Rep, class Period> Duration checked_convert(std::chrono::duration<Rep, Period> d) { using namespace std::chrono; using S = duration<double, typename Duration::period>; constexpr S m = Duration::min(); constexpr SM = Duration::max(); S s = d; if (s < m || s > M) throw std::overflow_error("checked_convert"); return duration_cast<Duration>(s); } int main() { using namespace std::chrono; std::cout << checked_convert<nanoseconds>(10'000h).count() << "ns\n"; std::cout << checked_convert<nanoseconds>(10'000'000h).count() << "ns\n"; }
For me, these outputs are:
36000000000000000ns libc++abi.dylib: terminating with uncaught exception of type std::overflow_error: checked_convert
source share