Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does static_cast<T> do to a T&?

So I asked this question and I was tinkering around with solving it via static_cast. (Incidentally it does solve the problem, I'm just not sure if I understand why.)

In the code:

vector<int> foo = {0, 42, 0, 42, 0, 42};
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13);

Is the static_cast simply constructing an R-Value int? What's the difference between that and just the call:

replace(begin(foo), end(foo), int{foo.front()}, 13);

EDIT:

As inferred by the answers static_cast does seem to construct an R-Value int: http://ideone.com/dVPIhD

But this code does not work on Visual Studio 2015. Is this a compiler bug? Test here: http://webcompiler.cloudapp.net/

like image 893
Jonathan Mee Avatar asked Jun 22 '16 13:06

Jonathan Mee


2 Answers

  1. Yes, it is the same as int{...}, unless .front() returned a type that required a narrowing conversion. In that case, int(...) would be identical.

  2. In the case of programmer error, static cast is marginally less likely to do something dangerous, like convert a pointer into an int than int(...).

Note eliminating the cast results in undefined behaviour as the front element is modified by the replace operation, and that could break std::replace.

I would use

template<class T>
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); }

myself here.

As for why this isn't working in MSVC...

MSVC helpfully takes situations where you cast a variable of type T to a T and proceeds to do nothing. This breaks your code.

There is a compiler flag (/Zc:rvalueCast) you can use to make MSVC no longer break your code.

like image 172
Yakk - Adam Nevraumont Avatar answered Nov 05 '22 13:11

Yakk - Adam Nevraumont


Member function front returns a reference to the first element of a non-empty vector.

On the other hand standard algorithm replace declared like

template <class ForwardIterator, class T>
  void replace (ForwardIterator first, ForwardIterator last,
                const T& old_value, const T& new_value)

takes the third parameter also by reference. Thus in general the first element of the vector can be changed by the algorithm and as result processing of other elements of the vector by the algorithm can be incorrect.

Using static_cast a temporary object is created and will not be changed by the algorithm So the processing of all elements of the vector will be correct.

As for me then I suggested a C++ proposal to use keyword auto in such cases. For example

replace(begin(foo), end(foo), auto( foo.front() ), 13);
like image 35
Vlad from Moscow Avatar answered Nov 05 '22 12:11

Vlad from Moscow