2021-02-28

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

No comments:

Post a Comment