4

As titled.

For example, let's say we have an int8_t value "-10", I want to have a dynamic check (runtime value) in my program whether this exact integer value -10 can be safely held by a uint32_t variable after std::trunc. And in this case, since this is a negative value, so it CANNOT be held by an unsigned type. How can I do this in C++ code? Since if I use the normal comparison way, the implicit conversion would ruin the typing information like below. Is there any other simple way to do this?

  int8_t v = -10; 
  if (v <= std::numeric_limits<uint32_t>::max() &&
      v >= std::numeric_limits<uint32_t>::min()) {
    // It will be true here.
  }

I want to find a sound way to check whether the available value range of the target type can totally cover all the available values of the source type. Meaning after the explicit conversion, the result value should be exactly the same as the original one.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Jason Yu
  • 1,886
  • 16
  • 26
  • I'd suggest using a library that provides either a wrapper type that handles conversions in the way you want ([`safe_int`](https://www.boost.org/doc/libs/1_73_0/libs/safe_numerics/doc/html/safe.html) comes to mind) or a checked cast (e.g., `gsl::narrow_cast`). There's definitely prior work out there dedicated to this. – chris Jun 21 '21 at 01:06
  • Negative numbers typically share bit representation in memory with unsigned integers and only the type tells you which it is. Maybe if you use the signed integer limits or some sort of `BigInt` check perhaps this would be ok. – CinchBlue Jun 21 '21 at 01:14
  • Converting -10 to `std::uint32_t` is well defined. But if you want to avoid converting negative values to unsigned types, that’s trivial. `if (v < 0) dontdoit;` – Pete Becker Jun 21 '21 at 01:23
  • The built-in integer types can't do that, we may also consider use boost.It is more versatile than the libraries mentioned earlier – prehistoricpenguin Jun 21 '21 at 01:42
  • First handle the signed/unsigned check seperately - this is easy, check if the value is negative when the target type is unsigned and the source type is signed. If that check succeeds, convert both the value to check and the limits of the target type to the largest integral type available on your platform, and perform that comparison with those extended values, where you can be sure no overflow/underflow would occur. – user2407038 Jun 21 '21 at 02:32
  • duplicates: [Function checking if an integer type can fit a value of possibly different (integer) type](https://stackoverflow.com/q/17224256/995714), [How to test if a constant fits into a type while compiling?](https://stackoverflow.com/q/3634834/995714), [Checking at compile time if specified value is in a range of a type](https://stackoverflow.com/q/5556466/995714), [How to check if value will fit into type?](https://stackoverflow.com/q/22157923/995714) – phuclv Jun 21 '21 at 02:45
  • No there isn't. Converting `-10` to an unsigned int is a defined behavior, in other words, in C++ eyes, it is totally allowed. If you want to forbid it, you have to define your own function to tell the machine your own rule. – Yves Jun 21 '21 at 03:12

1 Answers1

9

In C++20 you can use std::in_range

if constexpr (std::in_range<std::uint32_t>(v)) ...

See also Function checking if an integer type can fit a value of possibly different (integer) type


There's also intcmp to do comparisons yourself

if constexpr (std::cmp_greater(v, std::numeric_limits<uint32_t>::min())
           && std::cmp_less(v,    std::numeric_limits<uint32_t>::max()))
{
    ...
}
phuclv
  • 37,963
  • 15
  • 156
  • 475