Как запретить назначение

Есть ли причина использовать "канонические" сигнатуры для operator=

class X {
  X& operator=(const X&) = delete;
  X& operator=(X&&) = delete;
};

вместо

class X {
  void operator=(X) = delete;
};

когда все, что вы хотите сделать, это delete it?

Upd:
Также рассмотрим ситуацию, когда X имеет явно объявленный конструктор перемещения или копирования.

class X {
public:
  X(X&&);
};

В этом случае op=(X&&) и op=(const X&) неявно удаляются, но я хочу явно выразить, что назначение не разрешено.

Ответ 1

Нет, нет технической причины использовать подпись оператора канонического копирования.

Как видно из стандарта, [dcl.fct.def.delete] §8.4.3:

  1. Программа, которая ссылается на удаленную функцию неявно или явно, кроме объявления, плохо сформирована. [Примечание: это включает вызов функции неявно или явно и формирование указателя или указателя на элемент к функции. Он применяется даже для ссылок в выражениях, которые потенциально не оцениваются. Если функция перегружен, он ссылается только в том случае, если функция выбрана с помощью разрешения перегрузки. - конец примечания]

Поэтому имя удаленной функции, в данном случае operator=, может использоваться только в том случае, если компилятор находит предпочтительное разрешение перегрузки. Однако такая перегрузка не может существовать, поскольку X и const X& неотличимы как параметры ([over.ics.rank] §13.3.3.2), а возвращаемое значение игнорируется.

Говоря, существует стилистическая причина использовать каноническую подпись. Сам факт, что этот вопрос существует, показывает, что любой, кто читает ваш код, может не знать смысла и предположить, что он делает что-то особенное. Для удобства чтения я бы рекомендовал вам использовать знакомый X& operator=(const X&) = delete;.