0
int1_type x = ...;
int2_type y;

if ([check whether the current value of x will fit into y]) {
   y = x;
}

Is there a generic way to check if the current value of x will fit into y (eg. long x = 1; char y = x;) when their types depend on platform and/or template specializations?

lamefun
  • 3,862
  • 4
  • 20
  • 22

6 Answers6

1

Your intention is to assign it. A lossy assignement on basic type will never corrupt your program so:

template<typename T> int sign(T data) {
  return (data>=0) - (data<0);
}

template<typename T, typename K> bool test(T source, K target) {
  target = (K)source;
  return (source == target) && (sign(source)*sign(target)>=0);
}

simply write

if (test(x,y)) {
 y = x;
}
Stefano Buora
  • 1,052
  • 6
  • 12
  • Is it guaranteed by the standard that it'll never corrupt the program? I know that integer overflows are undefined behavior, isn't lossy assignment that leads to integer overflow a UB too? – lamefun Oct 24 '14 at 07:28
  • The undefined behaviour is about the new value contained in the "smaller" integer. It states that you cannot do assumption about the new value in the smaller integer after losing data. – Stefano Buora Oct 24 '14 at 07:30
  • I thought UB can be literally anything. Where does the standard say that I'm ok if I don't assume anything about the new value? – lamefun Oct 24 '14 at 07:36
  • I've update the answer. There was a problem with int x = - 1 and unsigned long as y type. – Stefano Buora Oct 24 '14 at 07:40
  • Updated adding function sign() as suggested in http://stackoverflow.com/questions/14579920/fast-sign-of-integer-in-c – Stefano Buora Oct 24 '14 at 07:41
  • This solution doesn't require C++11 – Stefano Buora Oct 24 '14 at 12:05
1
template<typename T, typename U>
bool will_fit(U u, T t = T())
{
    auto const Tmax = std::numeric_limits<T>::max();
    auto const Tmin = std::numeric_limits<T>::min();

    if (std::numeric_limits<U>::is_signed)
    {
        if (std::numeric_limits<T>::is_signed)
            return u >= (std::intmax_t)Tmin && u <= (std::intmax_t)Tmax;
        return u >= 0 && u <= (std::uintmax_t)Tmax;
    }
    else
        return u <= (std::uintmax_t)Tmax;
}

With some SFINAE tricks, some of those runtime checks can be made into compile time checks, but I'll leave that for you to investigate, if performance is an issue.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
0

If you can be restricted to PODs.

There is CHAR_BIT which holds how many bits in a char.

I guess you could do for unsigned types:

if ((x >= 0) &&  (x < pow(2, CHAR_BIT * sizeof y))){
  y = x;
}
RedX
  • 14,749
  • 1
  • 53
  • 76
0

The expression y will fit the current value of x is rather unclear.

If you meant the value of y will fit (into) the type of x, then you can use this:

if (sizeof(int2_type) <= sizeof(int1_type) || (int2_type)(int1_type)y == y)
{
    // the value of y fits into the type of x
}
barak manos
  • 29,648
  • 10
  • 62
  • 114
0

This one uses and to check ranges and signs of the values:

#include <limits>
#include <type_traits>

template<typename T> T max_for(T) { return std::numeric_limits<T>::max(); }
template<typename T> T min_for(T) { return std::numeric_limits<T>::min(); }
template<typename T> bool is_signed(T) { return std::is_signed<T>::value; }
template<typename T1, typename T2> bool same_sign(T1, T2) {
    return std::is_signed<T1>::value == std::is_signed<T2>::value; }

template <typename T1, typename T2>
bool fits(T1 src, T2 dst)
{
    auto valid_signed_to_unsigned =
        (is_signed(src) && !is_signed(dst) && src >= 0 && src <= ((max_for(dst) -1) / 2));

    auto valid_unsigned_to_sign =
        (!is_signed(src) && is_signed(dst) && src <= max_for(dst));

    auto valid_same =
        same_sign(src, dst) && src >= min_for(dst) && src <= max_for(dst);

    if (valid_signed_to_unsigned || valid_unsigned_to_sign || valid_same)
    {
        return true;
    }

    return false;
}
heksesang
  • 171
  • 6
  • It doesn't work for: int src= -1; unsigned int dst; The function will return true. (I had some warning for signed/unsigned missmatch) – Stefano Buora Oct 24 '14 at 12:19
-2

Use the numeric limits template to find the maximum, with a helper function for type deduction:

#include <limits>

template<typename T> max_for(T) { return std::numeric_limits<T>::max(); }
template<typename T> min_for(T) { return std::numeric_limits<T>::min(); }

if (x >= min_for(y) && x <= max_for(y))
  y = x;   // type of y can accomodate the value x
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • @lamefun The idea was to demonstrate type deduction. See other answers (e.g. [this one](http://stackoverflow.com/a/26544263/1600898)) for more complete implementations. – user4815162342 Oct 24 '14 at 10:32