I have this function:
fstream open_user_file() const
{
...
}
but my compiler complains about fstream
copy-constructor being implicitly deleted. Given that the compiler performs RVO, why is the copy constructor chosen instead of the move constructor?
Otherwise, what's the best way to do this?
The currently accepted answer is just wrong.
When returning a local variable with automatic storage, of the same type as the declared return type of the function, then there is a two phase process going on:
fstream open_user_file() const
{
fstream f;
/*...*/
return f;
}
The selection of the constructor for the copy is first performed as if the object were designated by an rvalue.
If the first overload resolution fails or was not performed, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue.
This means that if f
is move constructible, that will be preferred (and possibly elided) for returning f
. Else if f
is copy constructible that will be done (and possibly elided) for returning f
. Otherwise f
can not be returned from this function and a compile-time error should result.
The only case in which:
return std::move(f);
should help is when the implementation is buggy. In a conforming implementation, fstream
is move constructible and:
return f;
will be optimal. If f
is not move constructible, then:
return std::move(f);
won't help in a conforming implementation. And if coded anyway in a conforming implementation will have the effect of a pessimization, in that it will inhibit RVO.
gcc 4.8 has not implemented movable streams (and streams are not copyable). And this is the source of your problem. In C++98, C++03, and gcc 4.8, streams are not returnable from functions. In C++11 they are.