Przypisanie kopiowania / przenoszenia w std :: vector :: erase () i std :: deque :: erase ()

135

Odpowiadając na inne pytanie, natknąłem się na nieco inne sformułowania dla std::vector::erase()i std::deque::erase().

Oto, o czym mówi C ++ 14 std::deque::erase( [deque.modifiers]/4-6wyróżnienie moje):

Efekty: ...

Złożoność: liczba wywołań do destruktora jest taka sama, jak liczba usuniętych elementów, ale liczba wywołań operatora przypisania jest nie większa niż mniejsza z liczby elementów Przed skasowanymi elementami i liczba elementów po wymazane elementy.

Zgłasza: nic, chyba że konstruktor kopiujący, konstruktor przenoszenia, operator przypisania lub operator przypisania przenoszenia nie zgłosi wyjątku T.

A oto, o czym mówi std::vector::erase( [vector.modifiers]/3-5):

Efekty: ...

Złożoność: destruktora Tnazywa się liczbę razy, w liczbie równej liczbie elementów usunięte, ale ruch operatorowi przypisanie z Tnazywa się liczbę razy, w liczbie równej liczbie elementów w wektorze po skasowanych elementów.

Zgłasza: nic, chyba że konstruktor kopiujący, konstruktor przenoszenia, operator przypisania lub operator przypisania przenoszenia nie zgłosi wyjątku T.

Jak widać, specyfikacje wyjątków dla obu z nich są takie same, ale std::vectorwyraźnie wspomniano, że wywoływany jest operator przypisania przeniesienia.

Istnieje również zapotrzebowanie na Tsię MoveAssignabledo erase()pracy z obu std::vectori std::deque(tabela 100), ale nie oznacza to obecność operatora przypisania ruch: można zdefiniować operatorowi przypisanie kopiowania i nie określają ruch operatora zadanie, a to klasa być MoveAssignable.

Na wszelki wypadek sprawdziłem za pomocą GCC i Clang i rzeczywiście std::vector::erase()wywołuje operatora przypisania kopiowania, jeśli nie ma operatora przypisania przeniesienia, i std::deque::erase()robi to samo ( DEMO ).

Pytanie brzmi więc: czy coś przeoczyłem, czy to jest (redakcyjna) kwestia w standardzie?

Aktualizacja: przesłałem nr 2477 LWG .

Anton Savin
źródło
14
Wydaje się, że wada w standardzie.
Barry
4
^ Ack. Kwestia LWG byłaby odpowiednia.
Columbo,
4
Zwykle projekt standardu jest wystarczająco dobry. To jeden z tych przypadków, w których powinieneś patrzeć na rzeczywistość.
Mark Ransom
3
@MarkRansom bieżące źródło standardu dla std :: deque i std :: vector jest takie samo jak w pytaniu, więc prawdopodobieństwo, że ostateczna wersja się różni, jest bardzo małe.
Anton Savin
3
N4141 ma takie samo brzmienie jak N4140.
Brian,

Odpowiedzi:

9

Na spotkaniu Lenexa problem uzyskała status natychmiastowy wraz z proponowanym rozwiązaniem:

To sformułowanie odnosi się do N4296.

Zmień 23.3.3.4 [deque.modifiers] / 5 na:

-5 Złożoność : liczba połączeń z destructor odT jest taka sama jak liczba elementów usunięte, ale liczba połączeń do operatora przypisania zT nie więcej niż mniejsza od liczby elementów jest przed usunięte elementy i liczba elementów po usuniętych elementach.

Zmień 23.3.6.5 [modyfikatory wektorów] / 4 na:

-4- Złożoność : Destruktor programu Tjest nazywany liczbą razy równą liczbie usuniętych elementów, ale operator przypisania przesunięciaT nazywany jest liczbą razy równą liczbie elementów w wektorze po usuniętych elementach.

Oznacza to, że jeśli rezolucja zostanie przyjęta, nie będzie specjalnej wzmianki o przydziale ruchu std::vector::erase, a także sformułowanie std::deque::erasezostanie nieco wyjaśnione.

Anton Savin
źródło