Pibben
Pibben

Reputation: 2025

Compilers behave differently with regards to std::move and deleted copy constructor

#include <utility>

struct A {};

struct B {
  B(A&&) {}
  B(const B&) = delete;
};

static void func(B) {}

int main() {
  A a;
  func(std::move(a));
}

This program is accepted by:

Was the standard changed regarding this in C++17? Is MSVC wrong in accepting this before C++17?

Upvotes: 3

Views: 63

Answers (1)

songyuanyao
songyuanyao

Reputation: 172954

MSVC is wrong. For guaranted copy elision since C++17,

The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:

  • In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:

Given func(std::move(a));, std::move(a) is used to construct a temporary B via B::B(A&&) firstly, then the temporary is copied as the parameter to func via B::B(const B&). The copy operation is omitted at all, the parameter is constructed from std::move(a) directly via B::B(A&&).

Before C++17, this is an optimization, the copy/move constructor still must be present and accessible.

Upvotes: 4

Related Questions