Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ casting between numeric types

Tags:

c++

casting

I am aware that the different casting operators in C++ have already been discussed here many times but my question is specifically about casting between numeric types, not about the general differences between C style and C++ style operators. I consider this a completely different topic than casting within a class hierarchy.

Say I want to cast an int i to a double, some of the options I have are

static_cast<double>(i)
(double) i
double(i)

Personally I prefer the constructor-like style in the 3rd line in this case because I like to express that this is not a cast beteen class types, where I would certainly use static_cast or dynamic_cast.

Except from making it difficult to find this type of cast when searching in a text editor, are there any drawbacks of my choice?

like image 883
Frank Puffer Avatar asked Feb 18 '16 12:02

Frank Puffer


2 Answers

static_cast<double>(i) is certainly the clearest expression of your intent in this particular case.

When casting between numeric types, you are often a stone's throw away from undefined behaviour. So be careful in general. Although your cast is defined for every possible value of i, casting a double to an int could overflow the int, and that behaviour is undefined in C++.

I would always advise your checking if the destination type can accommodate the source type. std::numeric_limits<>::max() etc. can help here.

The C++ standard does not specify a maximum size of int (although 16, 32, and 64 bit 2's complement are common), so, potentially it might not be representable as a double.

In my code I have a namespace containing

  template<
        typename T/*the desired type*/,
        typename/*the source type*/ Y
    > T integral_cast(const Y& y)
    {
        static_assert(false, "undefined integral_cast");
    }

which I specialise for every numeric cast I need.

like image 121
Bathsheba Avatar answered Nov 09 '22 13:11

Bathsheba


One major drawback of those approaches is the cast is not safe against overflows, and other numeric errors.

Using static_cast is the immediate sane solution and this method is not flagged by static code analysts tools like PVS studio. the (double)i approach generates a warning.

Probably the safest approach is to have your own cast let's say numeric_cast<T>()

template <class OT, class ST>
OT numeric_cast(const ST value)
{
    return static_cast<OT>(value);
}

The advantage of this function is that you can do bound checks and other numeric checks to ensure that the cast is legitimate and does not return (or get) junk values.

There is another way of dealing with numbers but it only work with constant compile-time values. For this check user defined string literals

like image 42
Raxvan Avatar answered Nov 09 '22 13:11

Raxvan