6

Suppose in the below function:

template<typename T, typename U>
bool IsRepresentable(U u);

that T and U are non-bool integral types.

If the integer value of u is representable in T then IsRepresentable should return true, otherwise it should return false.

What's the best way to implement IsRepresentable in C++17? (or is there an exisiting similar function in the standard library?)

(My current thinking was a constexpr if-else chain around std::is_signed / sizeof / std::numeric_limits - but am I missing some easier or more straightforward way?)

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319

2 Answers2

3

The best I can imagine, in a simple way, is check if T(u) == u and the signs of u and T(u) are the same

I mean something as

template <typename T, typename U>
bool IsRepresentable (U const & u)
 { return (T(u) == u) && (T(u) > T(0)) == (u > U(0)); }
max66
  • 65,235
  • 10
  • 71
  • 111
  • Not bad. I think you could write it `T(u) == u && T(u) > T(0) == u > U(0)`. Any reason that would be worse? – Andrew Tomazos Nov 06 '19 at 12:36
  • @AndrewTomazos - D'Oh! You're right: works and it's clearer if I can simply check the equality between the two boolean values. Corrected. – max66 Nov 06 '19 at 12:47
1

As an alternative to accepted answer, I suggest You use a boost::numeric_cast. Sample usage:

https://coliru.stacked-crooked.com/a/c39d5c9e7aed26ad

#include <boost/numeric/conversion/cast.hpp>
#include <iostream>

int main()
{
    using boost::numeric_cast;

    using boost::numeric::bad_numeric_cast;
    using boost::numeric::positive_overflow;
    using boost::numeric::negative_overflow;

    try
    {
        int i=42;
        short s=numeric_cast<short>(i); // This conversion succeeds (is in range)
    }
    catch(negative_overflow& e) {
        std::cout << e.what();
    }
    catch(positive_overflow& e) {
        std::cout << e.what();
    }

    try
    {
        int i=70000;
        short s=numeric_cast<short>(i); // ad numeric conversion: positive overflow
    }
    catch(negative_overflow& e) {
        std::cout << e.what();
    }
    catch(positive_overflow& e) {
        std::cout << e.what();
    }
}
marcinj
  • 48,511
  • 9
  • 79
  • 100