Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run-time check of integral conversion

Tags:

c++

c++17

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?)

like image 834
Andrew Tomazos Avatar asked Nov 06 '19 11:11

Andrew Tomazos


2 Answers

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)); }
like image 135
max66 Avatar answered Sep 19 '22 09:09

max66


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();
    }
}
like image 39
marcinj Avatar answered Sep 19 '22 09:09

marcinj