Best practice in C++ for casting between number types
Just use static_cast
. The problem with C casts is the ambiguity of the operation (i.e. point (1) of Explicit type conversion).
C++ casts avoid this. Additionally C++ casts are more visible when searching for them.
Using Stroustrup's words (What good is static_cast?):
Even an innocent-looking cast can become a serious problem if, during development or maintenance, one of the types involved is changed. For example, what does this mean?:
x = (T)y;
We don't know. It depends on the type
T
and the types of x and y.T
could be the name of a class, atypedef
, or maybe a template parameter. Maybex
andy
are scalar variables and(T)
represents a value conversion. Maybex
is of a class derived fromy
's class and(T)
is a downcast. Maybex
andy
are unrelated pointer types. Because the C-style cast(T)
can be used to express many logically different operations, the compiler has only the barest chance to catch misuses. For the same reason, a programmer may not know exactly what a cast does. This is sometimes considered an advantage by novice programmers and is a source of subtle errors when the novice guessed wrong.The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors.
[CUT]
A secondary reason for introducing the new-style cast was that C-style casts are very hard to spot in a program. For example, you can't conveniently search for casts using an ordinary editor or word processor.
[CUT]
casts really are mostly avoidable in modern C++
Also consider boost::numeric::converter
/ boost::numeric_cast
that are safer alternatives (part of Boost.NumericConversion library).
E.g.
#include <iostream>
#include <boost/numeric/conversion/cast.hpp>
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(); }
return 0;
}
In general for both implicit conversions and explicit conversions (through static_cast
) the lack of preservation of range makes conversions between numeric types error prone.
numeric_cast
detects loss of range when a numeric type is converted and throws an exception if the range cannot be preserved.
Related videos on Youtube
keith
Updated on June 15, 2022Comments
-
keith almost 2 years
What is the best practice for casting between the different number types? Types
float
,double
,int
are the ones I use the most in C++.An example of the options where
f
is afloat
andn
is adouble
or anint
:float f = static_cast<float>(n); float f = float(n); float f = (float)n;
I usually write
static_cast<T>(...)
but wondered if there was any consensus within the C++ development community if there is a preferred way.I appreciate this is may end up being an opinion based question and there may not be a "standard" way, in which case please let me know that there is no standard way so at least I know that :-)
I know this question has cropped up in relation to casting in general, however, I am interested specifically in numbers and whether there are specific best practices in the approach for number types.
-
Ivan Aksamentov - Drop almost 8 yearsThe best practice would be to write a program that would not need any casts
-
keith almost 8 years@Cody Gray, my question is specific to numbers which I'm sure other people may be interested in understanding if the general case applies to. It was not really my intention to imply that I was speculating on whether C++ 11 differs from earlier versions.
-
keith almost 8 years@Drop, which only works if you are writing the code from scratch and there are no type differences between third party libraries and you are not using double for accuracy and then floats for vectorization, and many other reasons why casting between numbers is quite typical in scientific computing.
-
Cody GrayThis has not changed in C++11; the same rules apply as under earlier versions of the standard. See linked duplicate question for details, and this one, too.
-
-
eerorika almost 8 years"sometimes it's a conversion ... sometimes it's a cast" doesn't make much sense to me. A cast is an explicit conversion, is it not?.
-
manlio almost 8 years@user2079303 You are right: it's "Google's terminology" (google.github.io/styleguide/cppguide.html#Casting) but it doesn't exactly match regular C++ usage (stackoverflow.com/q/4337306/3235496). I've change that line to avoid misunderstandings.
-
eerorika almost 8 yearsThanks for the link. It will help when I stumble on that terminology in future. Too bad the guide doesn't explain the difference between a cast and a conversion in their terminology.
-
Trevor Boyd Smith almost 6 years@manlio if boost is not an option, here is a re-implementation of
boost::numeric_cast
using only code available instd
library: stackoverflow.com/a/49658950/52074