move semantics unused in presence of std::move

415 Views Asked by At

With the following:

#include <iostream>
#include <fstream>
using namespace std;
int main() {
    ifstream f;
    ifstream g;
    f = std::move(g);
}

Why is ifstream::operator=(const ifstream&) being called instead of ifstream::operator=(ifstream&&) even though std::move() is called?

Update: Generally speaking, is there a way to coerce a lvalue reference to a rvalue reference?

2

There are 2 best solutions below

3
On BEST ANSWER

What evidence do you have that ifstream::operator=(const ifstream&) is being called? Do you get a compile error that says you're calling this private or deleted member?

If your code is calling ifstream::operator=(const ifstream&), and if your implementation is claiming to be C++11, then this is a bug in either your C++ std::lib, or compiler. When I compile your code, ifstream::operator=(ifstream&&) gets called. And this is by design.

I stuck a print statement in my implementation of ifstream::operator=(ifstream&&) just to be sure. When I did your program prints out:

basic_ifstream<_CharT, _Traits>::operator=(basic_ifstream&& __rhs)
1
On

Standard

 27.9.1.8 Assign and swap [ifstream.assign]

       basic_ifstream& operator=(basic_ifstream&& rhs);

I assume you are looking at the wrong code (nowhere is it guaranteed that the base class operator istream::operator=(istream&&) must be called)?


Update: Generally speaking, is there a way to coerce a lvalue reference to a rvalue reference?

Yes, it is what std::move does:

template <class T> typename remove_reference<T>::type&& move(T&& t) noexcept;

There is also

template <class T> typename conditional<
  !is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value,
  const T&, T&&>::type move_if_noexcept(T& x) noexcept;

which does the same, provided that the moveconstructor is nothrow.