Скопировать elision (NRVO) с удаленным копированием и перемещением конструкторов возможно?

В cppreference сказано, что

Конструкторы копирования/перемещения не должны присутствовать или быть доступными в операторе return, когда операнд является значением prvalue того же типа класса (игнорируя cv-квалификацию), что и возвращаемый тип функции:

T f() {
    return T();
}

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

Правильно ли я понимаю, и для того, чтобы приведенный выше пример работал, неизбежно иметь хотя бы один конструктор копирования или перемещения?

Я пробовал следующее:

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();

Почему этот код компилируется и работает? Насколько я понимаю, на самом деле метод getEmptyPlayer() должен вызывать конструктор копирования для копирования объекта при возврате. Из-за повышения эффективности компилятором это не так, но исключение копирования (NRVO) приходит на смену и напрямую создает объект там, где он должен быть, а не делает копию. Тем не менее, cppreference (см. выше) говорит, что должен существовать доступный или присутствующий конструктор копирования/перемещения. Так что же здесь происходит?

Заранее спасибо!


person AnUser1    schedule 09.04.2020    source источник
comment
Там написано, что они не должны присутствовать. То есть они не нужны   -  person sparik    schedule 09.04.2020
comment
Я не понимаю вопроса. В цитате говорится, что конструкторы копирования/перемещения не обязательно должны присутствовать или быть доступными, так почему же неизбежно иметь хотя бы один конструктор копирования или перемещения? Кроме того, это RVO, а не NRVO.   -  person HolyBlackCat    schedule 09.04.2020
comment
Я не могу в это поверить. Я просто не могу читать. То, что я пропустил, это не. Теперь я понимаю, почему люди пишут это жирным шрифтом...   -  person AnUser1    schedule 09.04.2020


Ответы (2)


Вопрос абсолютная ерунда. В цитате говорится: «Конструкторы копирования/перемещения не должны не присутствовать [...]».

Ужасно извиняюсь, что невнимательно прочитал.

person AnUser1    schedule 09.04.2020

Скопировать elision (NRVO) с удаленным копированием и перемещением конструкторов возможно?

No.

Если есть копирование (или перемещение), то тип должен быть копируемым (или перемещаемым). Тот факт, что копирование (или перемещение) может быть оптимизировано, не делает такую ​​программу правильной.

Почему этот код компилируется и работает?

Потому что нет копирования (или перемещения) (начиная с С++ 17).

Насколько я понимаю, на самом деле метод getEmptyPlayer() должен вызывать конструктор копирования для копирования объекта при возврате.

Это не так, начиная с С++ 17.

Раньше это было необходимо до С++ 17 (и вызов можно было исключить).

person eerorika    schedule 09.04.2020