3

Sometimes, we need to explicitly cast one numeric type to another (e.g. to avoid warning when we lose precision or range). For some:

double foo;

we could write:

(float)foo

but most C++ programmers say it's evil 'old-style cast' and you should use the 'new-style cast':

static_cast<float>(foo)

There is an alternative of boost::numeric_cast which is quite interesting (at least in not-performance-critical code) but this question is about static_cast.

A similar question was already asked, but the most important arguments used there are not valid for numerical cast (in my opinion, am I wrong?). There are they:

You have to explicitly tell the compiler what you want to do. Is it upcast, or downcast? Maybe reinterpret cast?

No. It is simple numeric cast. There is no ambiguity. If I know how static_cast<float> works, I know how does it work for 'old-style' cast.

When you write (T)foo you don't know what T is!

I'm not writting (T)foo but (float)foo. I know what is float.

Are there any important reasons for using a new, better casts for numeric types?

peper0
  • 3,111
  • 23
  • 35
  • 2
    Consistency is one reason. Also, I'm of the opinion casts should stand out as much as possible. I've also seen `#define STATIC_CAST(To,From) ((To)From)` in the wild once in a C code base. But it mattered to those devs far more than it did to me. – StoryTeller - Unslander Monica Nov 15 '18 at 10:34
  • 1
    Also, it's easier to textually search for casts. `(float)` can be part of function signature, opposed to `static_cast(` – Adam Kotwasinski Nov 15 '18 at 10:35
  • 2
    something like `(int)p;` will work fine as long as `p` is some number, however if `p` is actually a pointer to some number use of C-style cast will cause you to shot your own leg. Note that `static_cast` is a rather weak alternative so some projects are using even stricter casts that can express intent of value truncation / sign change and other things. – user7860670 Nov 15 '18 at 10:44

2 Answers2

1

In a general scenario (which you have mentioned) you'd want explicit C++ cast to avoid possible issues mentioned in When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used? (ability to devolve into reinterpret_cast).

In numeric scenario you get two benefits at least:

  • you don't need to remember that C-style cast for numerics safely devolves to static_cast and never reaches reinterpret_cast - I'd call it "ease of use" and "no surprises" part
  • you can textually search for cast operations (grep 'static_cast<double>' vs grep '(double)' which can be part of function signature)
Adam Kotwasinski
  • 4,377
  • 3
  • 17
  • 40
1

Like many things inherited from C, the more specific C++ variants are there to inform readers of the code, not the compiler.

You use static_cast<double> because it doesn't do all the things that (double) can.

The conversions performed by

  • a const_­cast,
  • a static_­cast,
  • a static_­cast followed by a const_­cast,
  • a reinterpret_­cast, or
  • a reinterpret_­cast followed by a const_­cast,

can be performed using the cast notation of explicit type conversion.

[expr.cast/4]

Specifying static_cast alerts you with a compile time error, rather than silently having undefined behaviour, if the expression you think is safe isn't.

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Can `(double)` do a `reinterpret cast`? How? – peper0 Nov 15 '18 at 11:01
  • @M.M `reinterpter_cast` from pointer to floating point types is not allowed, so C-style cast is not allowed either – user7860670 Nov 15 '18 at 11:06
  • OK. But even so, this is a specific case of a general rule to avoid C-style casts for the reasons given – M.M Nov 15 '18 at 11:14
  • 1
    @peper0 doesn't matter. `(double*)` *does*, and you should be consistent as to how you write casts. Like many things inherited from C, the *more specific* C++ variants are there to inform *readers* of the code, not the compiler – Caleth Nov 15 '18 at 11:15