Czytanie na nowo standardu, myślę, że to błąd.
Co oznacza standard?
8.5.1/2 Kiedy agregat jest inicjowany przez liście inicjatora, zgodnie 8.5.4, elementy listy inicjatora są brane jak inicjalizatory członów agregatu, w podnoszeniu indeksu dolnego lub elementu członkowskiego. Każdy element jest inicjowany w trybie kopiowania z odpowiedniej klauzuli inicjalizującej- .
To wyjaśnia, że:
8.5/14: (...) nazywa kopiowaniem inicjalizacji. [Uwaga: inicjowanie kopii może wywołać ruch (12.8). -wstrzymaj notatkę]
Ale nie znalazłem dowodów w 12.8, że w twoim konkretnym przypadku ruch byłby wymagany.
8.5.4/3 W przeciwnym razie, jeśli T jest typem klasy, konstruktorzy są uznawane. Jeśli T ma konstruktor listy inicjalizacyjnej, lista argumentów zawiera listę inicjalizatorów jako pojedynczy argument; w przeciwnym razie, lista argumentów składa się z elementów listy inicjalizatora. Odpowiednie konstruktory są wyliczane, a najlepiej wybrane poprzez rozdzielczość przeciążenia (13.3).
Zasadniczo kod powinien zadziałać!
Czy to błąd? Próbowałem eksperymentalnie
Skomentowałem usunięcie konstruktora ruchu, aby skorzystać z niejawnego konstruktora ruchu.O dziwo, otrzymałem następujący komunikat o błędzie:
Compilation error time: 0 memory: 3232 signal:0
prog.cpp: In constructor 'Aggr::Aggr()':
prog.cpp:19:28: error: use of deleted function 'A::A(const A&)'
Aggr() : arr{{"a"}, {"b"}} {}
^
prog.cpp:10:3: note: declared here
A(const A&) = delete
Teraz skarży się na brakujący konstruktor kopii!
Jeszcze dziwniej, więc podałem własny konstruktor ruchu zamiast domyślnego: tutaj skompilował kod pomyślnie!
Wreszcie warunkiem zarówno kopię oraz ruch i dodano kilka śledzenie:
class A {
private:
std::string s;
public:
A() = delete;
A(const A&) { std::cout<<"copy\n";} //= delete;
A(A&&) { std::cout<<"move\n";} //= delete;
A(const std::string &a) : s(a) { std::cout<<"string ctor\n";}
};
I kiedy utworzyć obiekt Aggr
, to po prostu wyświetla:
string ctor
string ctor
pokazując, że element tablicy jest zainicjowano formularz konstruktora ciągu za pomocą metody "copy elision", tak jak się spodziewaliśmy.
Wszystkie te testy przeprowadzono z gcc-9.4.2 na idee z opcją C++ 14.
Wnioski
Fakt, że ten sam kod nie skompilować z niejawnego przenieść ctor i udaje ze zdefiniowaną przez użytkownika posunięcie konstruktor wygląda bardzo poważnie jak robaka.
Fakt, że konstruktor ruchu nie jest używany, gdy jest dostępny, wzmacnia to wrażenie.
W związku z tym zgłosiłem this bug.
Dlaczego to jest "A &&"? – ZivS
@ZivS numer referencyjny rvalue – bolov
może odnosić się do twojego problemu: http://stackoverflow.com/questions/26685551/how-to-initialize-array-of-classes-with-deleted-copy-constructor-c11 – marcinj