Should I use static_cast in assignments and return statements and why?

903 Views Asked by At

Here are two very similar snippets:

vector<int> a;
int n = static_cast<int>(a.size());
// ---------
int f(const vector<int>& a) {
    return static_cast<int>(a.size());
}

Here I explicitly cast a value of type size_t to type int. If I omit static_cast then the same cast applies implicitly.

Of which kind would this implicit cast be? Is it safe to omit static_cast in explicit assignments and return statements?

3

There are 3 best solutions below

2
On BEST ANSWER

This cast is not that safe, actualy the value of n may be implementation defined (c++ standard [conv.integral]):

If the destination type is signed, the value is unchanged if it can be represented in the destination type otherwise, the value is implementation-defined.

If you enable all warning, and don't use the static_cast, your compiler may inform you about a narrowing conversion. If you use the static_cast, you inform reader of your code that you know for sure that a.size() <= std::numeric_limits<int>::max() or that you know what your implementation is going to do if such a condition does not hold.

(notice that it could be possible that previous comparison also invokes implementation defined conversion if std::size_t is smaller than int, the c++ standard allowes it)

0
On

This would be an integral conversion. And a narrowing one at that.

For the variable initialization, if you want a specific type, a good approach is to do what Herb Sutter suggests in his "Almost Always Auto" GotW article:

auto n = int{a.size()};

Use list initialization whenever possible. It will prevent narrowing conversions and you'll be flagged by your compiler to use an explicit cast when required (such as the case above).

0
On

The necessarily of casting is determined by the necessarily of conversion. So the real question here should "be why would I return / store an int instead of vector<int>::size_type?" If your program logic doesn't really require such conversion then don't perform it at all. If your program logic requires such conversion (for example you need to pass this value into a call to a third-party function that accepts int) then you should use static_cast. Omitting static_cast in this case would be a sign of unintended narrowing conversion and will trigger corresponding compiler warnings, such as warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data or warning: conversion to 'int' from 'std::vector<int>::size_type {aka long unsigned int}' may alter its value [-Wconversion]