Większość z nich została opisana w § 12.8. Paragraf 17 określa, co liczy się jako operatorów przypisania kopia użytkownika oświadczył:
Użytkownik zadeklarowana kopia przypisanie operatora X::operator=
jest non-static non-szablon funkcji członka klasy X
z dokładnie jeden parametr typu X
, X&
, const X&
, volatile X&
lub const volatile X&
.
Paragraf 19 określa, co liczy się jako move operatorów przypisania użytkownika oświadczył:
Użytkownik zadeklarowana ruch przypisanie operatora X::operator=
jest non-static non-szablon funkcji członka klasy X
z dokładnie jednym parametr typ X&&
, const X&&
, volatile X&&
lub const volatile X&&
.
Oznacza to, że jest to operator przydziału kopiowania, ale nie operator przeniesienia.
Paragraf 18 mówi, gdy kompilator generuje operatory przypisania kopiowania:
Jeżeli definicja klasy nie jawnie zadeklarować kopiowania przypisanie operatora, jeden jest zadeklarowany w sposób dorozumiany. Jeśli definicja klasy deklaruje konstruktor ruchu lub operator przypisania ruchu, domyślnie zadeklarowany operator przypisania kopiowania jest zdefiniowany jako usunięty; w przeciwnym razie wartość jest zdefiniowana jako domyślna (8.4).Ten drugi przypadek jest przestarzały, jeśli klasa ma deklarowany przez użytkownika konstruktor kopii lub zadeklarowany przez użytkownika destruktor z rodziny .
Paragraf 20 mówi nam, gdy kompilator generuje przenieść operatorów przypisania:
Jeżeli definicja klasy X nie jawnie zadeklarować ruch operator przypisania, jeden będzie niejawnie zadeklarowana jako domyślnie jeśli i tylko wtedy, gdy
[...]
- X nie posiada operator przypisania kopia użytkownika oświadczył
[...]
Ponieważ klasa ma zadeklarowany przez użytkownika operator przypisania kopiowania, żaden z plików niejawnych nie zostanie wygenerowany przez kompilator.
std::is_copy_assignable
i std::is_move_assignable
opisano w tabeli 49 jako posiadający tę samą wartość jak odpowiednio is_assignable<T&,T const&>::value
i is_assignable<T&,T&&>::value
. Tabela ta mówi nam, że is_assignable<T,U>::value
jest true
gdy:
Wyrażenie declval<T>() = declval<U>()
jest dobrze uformowane podczas leczenia jako unevaluated argumentu (klauzula 5). Kontrola dostępu jest wykonywana jako , jeśli w kontekście niezwiązanym z T
i U
. Bierze się pod uwagę wyłącznie bezpośredni kontekst wyrażenia przypisania.
Ponieważ zarówno declval<T&>() = declval<T const&>()
i declval<T&>() = declval<T&&>()
są dobrze uformowane dla tej klasy, to nadal liczy się jako kopię cesji i przenieść przypisane.
Jak już wspomniałem w komentarzach, to, co jest ciekawe, to fakt, że w obecności konstruktora ruchu, ten operator=
poprawnie wykona ruchy, ale technicznie nie będzie liczony jako operator przypisania ruchu. Jest jeszcze dziwniej, jeśli klasa nie ma konstruktora kopiowania: będzie miała operatora przypisania kopii, który nie wykonuje kopii, a jedynie ruchy.
Powiązane dyskusja: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value – mavam
Dostaję błędy kompilatora zarówno w Visual Studio jak i g ++, jeśli mam coś zarówno T & operator = (T t) i T & operator = (T && t), ponieważ jest niejednoznaczny – user929404
@ user929404: I powinieneś. Chodzi o to, że zastępujesz * obie * zadanie kopiowania i przenoszenia przy użyciu tylko wartości. –