Próbuję zrozumieć, jak związki zostały rozszerzone przez C++ 11. Jedną z rzeczy, która się zmieniła, jest możliwość korzystania teraz z niestatycznych elementów danych z nietrywialnymi specjalnymi funkcjami członków. Od cppreference.comZwiązki w C++ 11: domyślny konstruktor wydaje się być usunięty
Jeśli związek zawiera non-statycznego elementu danych z niebanalną specjalnej funkcji składowej (domyślnego konstruktora, kopiowanie/konstruktora przenosić, kopiować/cesja ruchu, lub destructor), że funkcja zostanie usunięta domyślnie w związku i musi zostać jednoznacznie określone przez programistę. Co najwyżej jeden element danych może mieć domyślny inicjator członu.
próbuję następujący kod:
struct X
{
~X() {};
};
union U
{
X x;
~U() {};
};
int main()
{
U s1{}; // works, probably aggregate initialization
U s2; // DOES NOT compile, why?
}
Tutaj X
(który służy jako członek danych unii) ma pod warunkiem użytkownika destruktora, stąd destruktora unia jest domyślnie usunięta. W związku z tym zapewniam jedno wyraźnie. Jednak kod nie skompilować, z błędem
notatka: „U :: U()” jest domyślnie usunięte, ponieważ definicja domyślny byłoby źle sformułowane:
Kod kompiluje jeśli Usuwam ostatnią linię U s2;
.
Pytanie Co się tutaj dzieje? Dlaczego kompiluje się U s1{};
, ale U s2;
nie? Czy domyślny ctor związku jest oznaczony jako usunięty (jeśli tak, to dlaczego ?!), a w pierwszym przypadku mamy właśnie inicjację agregującą? Zauważ, że jeśli dostarczę U(){}; // not U() = default;
, kod się skompiluje (ale nie, jeśli dostarczę tylko ctorowi z X
).
EDIT
Po wykopaniu w normie (N4527)
Związków: 9,5/2 [class.union]
[Uwaga: Jeśli którykolwiek niestatyczny element danych unii ma nietrywialny domyślny konstruktor (12.1), konstruktor kopiowania (12.8), konstruktor ruchu (12.8), operator przypisania kopiowania (12.8), operator przeniesienia przypisania (12.8) lub destruktor (12.4), odpowiedni członek func Unia musi być dostarczona przez użytkownika lub zostanie domyślnie usunięta (8.4.3) dla związku. -endnote]
wydaje się, że jest to błąd gcc (teraz zgłoszony here). Kod kompiluje się na clangu i gcc 4.8.2 lub wcześniejszym, łamie się na gcc4.9 i później (dzięki @ T.C. Za wskazanie). Kompilator: g ++ 5.3, -std=c++11
używany.
[Clang] (http://coliru.stacked-crooked.com/a/b58a360400009fa9) jest całkowicie zadowolony z tego kodu. To właściwie wygląda na błąd GCC. –
@ T.C. Tak, faktycznie widziałem to teraz po twoim komentarzu. Po raz pierwszy miałem wrażenie, że klang odrzucił go, mógł zostać przetestowany w zmodyfikowanej wersji. Zmieniono ostatnią linijkę pytania, dzięki. – vsoftco
@ T.C. Spróbuję zagłębić się w standard ... – vsoftco