Klammerentfernung bei std::array-Initialisierung

Lesezeit: 3 Minuten

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

Das Entfernen von Klammern gilt, aber nicht in C++11. In C++14 gelten sie wegen http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270 . Wenn Sie Glück haben, wird Clang das in ihren C++11-Modus zurückportieren (hoffen wir, dass sie es tun!).

  • Ab jetzt, clang-5.0 in archlinux wird das Entfernen von Klammern auch mit noch nicht unterstützt -std=c++17.

    – Victor Polevoy

    1. Oktober 17 um 12:43 Uhr

Relevant: http://en.cppreference.com/w/cpp/language/aggregate_initialization

Zusamenfassend,

struct S {
    int x;
    struct Foo {
        int i;
        int j;
        int a[3];
    } b;
};
S s1 = { 1, { 2, 3, {4, 5, 6} } };
S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax
S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign
                        // okay in C++14

.

491780cookie-checkKlammerentfernung bei std::array-Initialisierung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy