Angenommen, es gibt eine std::array
initialisiert werden. Es ist in Ordnung, wenn Sie doppelte Klammern verwenden:
std::array<int, 2> x = {{0, 1}};
std::array<int, 2> x{{0, 1}};
Es ist auch in Ordnung, einzelne geschweifte Klammern in der guten alten Aggregatinitialisierung zu verwenden, da das Entfernen der geschweiften Klammern die fehlenden geschweiften Klammern übernimmt:
std::array<int, 2> x = {0, 1};
Ist es jedoch in Ordnung, die Listeninitialisierung mit einzelnen geschweiften Klammern zu verwenden? GCC akzeptiert es, Clang lehnt es ab mit “kann Klammern um die Initialisierung des Unterobjekts nicht weglassen, wenn die direkte Listeninitialisierung verwendet wird”.
std::array<int, 2> x{0, 1};
Der einzige Teil des Standards, in dem das Entfernen von Klammern erwähnt wird, ist 8.5.1/12, in dem es heißt:
Alle impliziten Typkonvertierungen (Klausel 4) werden berücksichtigt, wenn das Aggregatmitglied mit einem Zuweisungsausdruck initialisiert wird. Wenn der Zuweisungsausdruck ein Mitglied initialisieren kann, wird das Mitglied initialisiert. Andernfalls, wenn das Mitglied selbst ein Unteraggregat ist, wird das Weglassen der geschweiften Klammern angenommen und der Zuweisungsausdruck wird für die Initialisierung des ersten Mitglieds des Unteraggregats berücksichtigt.
In 8.5.1 geht es speziell um die Initialisierung von Aggregaten, das sollte also bedeuten, dass Clang korrekt abgelehnt wird, oder? Nicht so schnell. 8.5.4/3 sagt:
Die Listeninitialisierung eines Objekts oder einer Referenz vom Typ T ist wie folgt definiert:
[…]
— Andernfalls, wenn T ein Aggregat ist, wird eine Aggregatinitialisierung durchgeführt (8.5.1).
Ich denke, es bedeutet, dass genau die gleichen Regeln wie bei der Aggregatinitialisierung gelten, einschließlich der Entfernung von geschweiften Klammern, was bedeutet, dass GCC korrekt akzeptiert wird.
Ich gebe zu, die Formulierung ist nicht besonders klar. Welcher Compiler hat also Recht mit der Behandlung des dritten Schnipsels? Tritt die Klammerentfernung bei der Listeninitialisierung auf oder nicht?
Gute Frage! Es könnte erwähnenswert sein, welchen Standard Sie verwenden. Der C++11-Standard, oder wenn nicht, welcher bestimmte Entwurf.
– Juanchopanza
7. Juni 13 um 13:50 Uhr
“zuweisungsähnliche Initialisierung” wird Kopier-Initialisierung genannt. Es ruft den Kopierkonstruktor auf, nicht den Zuweisungsoperator.
– TemplateRex
7. Juni 13 um 13:52 Uhr
@TemplateRex: deshalb habe ich die Arbeit “like” verwendet.
– Benutzer784668
7. Juni 13 um 13:53 Uhr
@juanchopanza: n3290, das mit dem Standard-IIRC identisch ist.
– Benutzer784668
7. Juni 13 um 13:53 Uhr
Es ist besser, die Standardterminologie zu verwenden, die Leute werden verwirrt und denken vielleicht, dass Sie es nicht verstanden haben, und führen Gespräche wie dieses 🙂
– TemplateRex
7. Juni 13 um 13:54 Uhr