MSVC cannot return an object that can be copied but cannot be moved
While fiddling around with copy elision I came across this strange behavior:
class Obj {
public:
Obj() = default;
Obj(Obj&&) = delete;
Obj(const Obj&) { std::cout << "Copy" << std::endl; }
};
Obj f1() {
Obj o;
return o; // error C2280: move constructor is deleted
}
Obj f2() {
Obj o;
return Obj(o); // this however works fine
}
int main() {
Obj p = f1();
Obj q = f2();
return 0;
}
GCC and Clang accept this code and are able to use copy elision in both cases.
In f1()
MSVC complains that it cannot return o
because the move constructor of Obj
is deleted. However, I would expect it to be able to fall back on the copy constructor. Is this a bug in MSVC or is this desired behavior (that I don't understand) and GCC / Clang are too permissive?
If I provide a move constructor, MSVC is able to elide the move when compiling as Release.
Interestingly MSVC is able to compile f2()
. As far as I understand this is due to the mandatory copy elision when the result of a constructor call is returned. However it feels counter-intuitive that I am only able to return o
by-value if I manually copy it.
I know that this situation might not be relevant for practical use since copyable objects usually are also moveable, but I am interested in the underlying mechanics.
Here is the online example for testing: https://godbolt.org/z/sznds7
from Recent Questions - Stack Overflow https://ift.tt/2NKG4Eg
https://ift.tt/eA8V8J
Comments
Post a Comment