Scott Meyers in his "Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14" discusses use of auto
in different contexts. He makes a point that sometimes auto
deducts incorrect type because normally, a developer would use (possibly unconsciously) implicit conversion like here:
std::vector<bool> vec = {true, false};
bool a = vec[0]
while using auto
like that:
std::vector<bool> vec = {true, false};
auto a = vec[0]
would yield a
to be std::vector<bool>::reference
so the author proposes to cast it before assignment:
auto a = static_cast<bool>(vec[0])
and I cannot understand why would I use auto
and static_cast<>
in this way if I can simply count on implicit conversion. I figured that maybe it is to highlight the fact that there is a conversion going on (to note it explicitly) but it still looks like an overkill to me. What would be the advantage of such solution?
Cheers!
There are a number of cases where static_cast
can help reduce both compiler ambiguities and also reader ambiguities when used with auto
.
Specifically, when considering std::vector<bool>
in the example, I can think of two such cases:
decltype(a)
to be a bool
rather than some std::__vector_bool_reference_wrapper
type, ora
were passed to a function with a signature that accepts a bool&
or bool*
, you would want this to be the correct type -- since implicit conversions will not occurThe above cases apply to anything that may have implicit conversions, not just bool
/reference-wrapper.
Additionally, cases get more interesting with other types.
Pointers:
nullptr
is of type decltype(nullptr)
which is also aliased as std::nullptr_t
. This is not any type T*
. Which means you can't write code like:
auto p = nullptr;
...
p = &a; // compile-error!
But instead would need:
auto p = static_cast<T*>(nullptr);
...
p = &a; // works!
Unintentional Promotions
Unintentional promotion can produce unexpected bugs. If code is using auto
and is relying on integer overflow, without being explicit about types, it is possible to unintentionally produce integer promotion -- which can prevent that overflow from occurring. This can produce subtle bugs in some code.
The same is likely possible with float
/double
promotion, though I'm having a harder time thinking of a case where such a case would be negative.
Unintended promotions can also cause compile-failures if the result is being passed to a function that expects a reference or pointer to T
of a different type than the promoted type is (similar to the vector<bool>
example above).
I'm sure other cases exist where static_cast
is significant when used with auto
, but in general the cases that come to mind deal with the strict typing that comes with overload resolution and template type deduction.
Other than that, there may also be cases where static_cast
just helps the general readability of complex functions that use a lot of auto