Большинство из них описано в разделе 12.8. Пункт 17 определяет, что считается пользователем объявлены операторами присваивания копии:
Пользователем объявленного оператором копирующего присваивания X::operator=
не является статической функцией, не являющегося члена шаблона класса X
только с одним параметром типа X
, X&
, const X&
, volatile X&
, или const volatile X&
.
Пункт 19 определяет, что считается пользователем объявлены операторами присваивания хода:
Пользователем объявленной оператор присваивания шага X::operator=
не является статической функцией члена не-шаблона класса X
с ровно один параметр тип X&&
, const X&&
, volatile X&&
, или const volatile X&&
.
Таким образом, он считается оператором присваивания копий, но не как оператором присваивания переадресации.
Пункт 18 говорит, когда компилятор генерирует операторы присваивания копирования:
Если определение класса не явно объявлять копию назначение оператора, один объявлен неявно. Если определение класса объявляет конструктор перемещения или оператор переадресации перемещения, неявный объявленный оператор назначения копирования определяется как удаленный; в противном случае он определяется как дефолт (8.4).Последний случай устарел, если класс имеет объявленный пользователем конструктор копирования или объявленный пользователем дескриптор .
Пункт 20 говорит нам, когда компилятор генерирует движение операторов присваивания:
Если определение класса X не явно объявить оператор присваивания шаг , один будет неявно объявлен дефолт, если и только если
[...]
- X не имеет пользовательскую объявленную оператор присваивания копии,
[...]
Поскольку у класса есть пользовательский оператор присваивания копии, ни один из неявных не будет сгенерирован компилятором.
std::is_copy_assignable
и std::is_move_assignable
описаны в таблице 49 как имеющее то же значение, соответственно is_assignable<T&,T const&>::value
и is_assignable<T&,T&&>::value
. Эта таблица говорит нам, что это is_assignable<T,U>::value
true
, когда:
Выражение declval<T>() = declval<U>()
хорошо образован при обработке в качестве невычисленного операнда (пункт 5). Проверка доступа выполняется как , если в контексте, не связанным с T
и U
. Рассматривается только актуальность непосредственного контекста выражения присваивания .
Так как declval<T&>() = declval<T const&>()
и declval<T&>() = declval<T&&>()
хорошо сформированный для этого класса, он по-прежнему считается копией назначаемой и двигаться переуступкой.
Как я уже упоминал в комментариях, все, что любопытно, заключается в том, что при наличии конструктора перемещения operator=
будет правильно выполнять ходы, но технически не считать оператором присваивания перемещения. Еще страннее, если класс не имеет конструктора копирования: у него будет оператор присваивания копии, который не делает копии, а только движется.
Связанное обсуждение: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value – mavam
Я получаю ошибки компилятора на Visual Studio и g ++, если у меня есть что-то как T & operator = (T t) и T & operator = (T && t), поскольку он неоднозначен – user929404
@ user929404: И вы должны. Дело в том, что вы заменяете * оба * копирование и перемещение присваиванием только с присвоением значения. –