Copy elision (NRVO) with deleted copy and move constructors possible?

651 Views Asked by At

In the cppreference it is said that

The copy/move constructors need not be present or accessible in a return statement, when the operand is a prvalue of the same class type (ignoring cv-qualification) as the function return type:

T f() {
    return T();
}

f(); // only one call to default constructor of T

Am I understanding this right and in order to make the above example work, it is inevitable to have at least one copy or move constructor?

What I tried is the following:

class Player
{
  //...
  public:
    Player();
    Player(std::string name);
    Player& operator=(const Player&) = delete;
    Player& operator=(Player&& p) = delete;
    Player(const Player& origin) = delete;
    Player(Player&& p) = delete;

    Player getEmptyPlayer() const {
      return Player("Name");
    }
}

//in main:

Player p1("It's Me");
Player p2 = p1.getEmptyPlayer();

Why is this code compiling and working? To my understanding actually the method getEmptyPlayer() would need to call the copy constructor for copying the object when returning. Due to efficiency improvements by the compiler this is not the case but the copy elision (NRVO) comes to turn and directly constructs the object where it should be and does not make a copy. Nonetheless, the cppreference (see above) says that an accessible or present copy/move constructor needs to exist. So what is happening here?

Thank you in advance!

2

There are 2 best solutions below

6
On

Copy elision (NRVO) with deleted copy and move constructors possible?

No.

If there is a copy (or move), then the type must be copyable (or movable). Just because the copy (or move) could be optimised away does not make such program well-formed.

Why is this code compiling and working?

Because there is no copy (nor move) involved (since C++17).

To my understanding actually the method getEmptyPlayer() would need to call the copy constructor for copying the object when returning.

It does not since C++17.

It used to be needed before C++17 (and the call could be elided).

0
On

The question absolute nonsense. The cite says "The copy/move constructors need not be present [...]".

I am terribly sorry for not reading correctly.