- that safe_signed_range and safe_unsigned_range have a default policy of native seems wrong to me.
In fact, the promotion policy can be eliminated entirely if the underlying type is always made automatic. safe<int> x( 5 ); // safe_base<INT_MIN, INT_MAX, throw_exception> safe<signed char> y( 5 ); // safe_base<SCHAR_MIN, SCHAR_MAX, throw_exception> auto z = x + y; // safe_base<INT_MIN+SCHAR_MIN, INT_MAX+SCHAR_MAX, throw_exception> safe<int> z = x + y; // converts above into safe<int>, checks Since the only visible effect of the promotion policy is to determine the first template parameter of the result, if there's no such template parameter, there'd be no need to determine it. Having both intmax_t and uintmax_t is a bit of a nuisance though, we still have to carry the 'signed' bit around.