-1

Here is the closest duplicate I could find.

Despite the tags, the question seems to be about C, and the usable answer references the C99 spec.

What is the correct way to handle this check in C++98, without using Boost or other libraries?

Community
  • 1
  • 1

1 Answers1

1

You can copy the code from gsl::narrow() and tweak it slightly, turning it into can_narrow() returning a bool rather than throwing:

// narrow_cast(): a searchable way to do narrowing casts of values
template<class T, class U>
inline constexpr T narrow_cast(U u) noexcept
{ return static_cast<T>(u); }

namespace details
{
    template<class T, class U>
    struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
    {};
}

template<class T, class U>
inline bool can_narrow(U u)
{
    T t = narrow_cast<T>(u);
    if (static_cast<U>(t) != u)
        return false;
    if (!details::is_same_signedness<T, U>::value && ((t < T{}) != (u < U{})))
        return false;
    return true;
}
Ðаn
  • 10,934
  • 11
  • 59
  • 95
  • Looks to me like can_narrow(2.0001) will return false, no? – Boris Glick Feb 09 '17 at 18:38
  • "Range check" is a question whether a _specific value_ can be safely reduced into a target type, rather than whether the source type range exceeds the target type range. As long as `u` is within `(std::numeric_limits::lowest(), std::numeric_limits::max())`, shouldn't the range check return true? – Boris Glick Feb 09 '17 at 18:54