2013-06-07 6 views

Odpowiedz

37

Twój problem związany jest z aggregate initialization: struct X jest agregatem, podczas gdy struct Y nie jest. Oto standardowa oferta dotycząca agregatów (8.5.1):

Agregat jest tablicą lub klasą (Klauzula 9) bez konstruktorów dostarczonych przez użytkownika (12.1), bez inicjalizatorów klamrowych lub równoważnych dla niestatyczni członkowie danych (9.2), brak prywatnych lub chronionych niestatycznych elementów danych (klauzula 11), brak klas bazowych (klauzula 10) i brak funkcji wirtualnych (10.3).

Ta klauzula określa, że ​​jeśli class ma klasę podstawową, to nie jest agregatem. Tutaj struct Y ma struct X jako klasę podstawową, a zatem nie może być typem złożonym.

dotyczące konkretnego problemu trzeba podjąć następującą klauzulę od normy:

Kiedy agregat jest inicjowany przez liście inicjatora, jak podano w 8.5.4, elementy listy inicjatora są brane jako inicjalizatory dla członków agregatu, w rosnącym indeksie dolnym lub członkowskim. Każdy element jest inicjowany podczas kopiowania z odpowiedniej klauzuli inicjalizującej. Jeśli inicjalizator-klauzula jest wyrażeniem i konwersja (8.5.4) jest wymagana do konwersji wyrażenia, program jest źle sformułowany.

Kiedy robisz X x = {0}, kruszywa inicjalizacji służy do zainicjowania a do 0. Jednak po wykonaniu Y y = {0}, ponieważ struct Y nie jest typem zagregowanym, kompilator będzie szukał odpowiedniego konstruktora. Ponieważ żaden z domyślnie wygenerowanych konstruktorów (domyślnie, kopiowanie i przenoszenie) nie może nic zrobić z jedną liczbą całkowitą, kompilator odrzuca twój kod.


Odnośnie tego odnośnika konstruktorów, komunikaty o błędach z brzękiem ++ są nieco bardziej wyraźne, co kompilator jest rzeczywiście próbuje zrobić (online example):

Y Y = {0}; 
^ ~~~ 

main.cpp:5:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Y &' for 1st argument 

struct Y : public X {}; 
    ^

main.cpp:5:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'Y &&' for 1st argument 

struct Y : public X {}; 
    ^

main.cpp:5:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided 

pamiętać, że istnieje a proposal, aby rozszerzyć inicjalizację agregacji, aby wesprzeć Twój przypadek użycia, i przekształcił się w C++ 17. Jeśli przeczytam go poprawnie, sprawi, że twój przykład będzie prawidłowy z oczekiwaną semantyką. Więc ... musisz tylko poczekać na kompilator zgodny z C++ 17.

+1

'clang ++ -std = C++ 1z' ​​wersja 4.0.1 kompiluje, ' g ++ -std = C++ 17' wersja 7.2.1 kompiluje, ale Visual Studio 2017 'cl' wersja 19.12.25816 jeszcze nie –

Powiązane problemy