41

Załóżmy, że jest zainicjowana std::array. To jest w porządku, jeśli stosowanie podwójnych nawiasów:Wyrównanie nawiasów w inicjalizacji std :: array

std::array<int, 2> x = {{0, 1}}; 
std::array<int, 2> x{{0, 1}}; 

To również dobrze używać pojedynczych szelki w starym dobrym łącznej inicjalizacji, jak elizja klamra zadba o brakujących szelek:

std::array<int, 2> x = {0, 1}; 

jest jednak czy można używać inicjowania listy za pomocą pojedynczych nawiasów klamrowych? GCC to akceptuje, Clang odrzuca je za pomocą "nie można pominąć nawiasów wokół inicjalizacji podobiektów przy użyciu bezpośredniego inicjowania listy".

std::array<int, 2> x{0, 1}; 

Jedyną częścią standard tam, gdzie jest klamra wyrzutnia Wspomniano 8.5.1/12, który mówi:

Wszystkie konwersje ukryte typu (punkt 4) są brane pod uwagę przy inicjalizacji łączny element z wyrażenie przypisania. Jeśli wyrażenie przypisania może zainicjować element, członek jest inicjowany. W przeciwnym razie, jeśli element sam w sobie jest podagregatem, zakłada się usztywnienie elipsy i wyrażenie przypisania jest brane pod uwagę przy inicjowaniu pierwszego elementu podagregatu.

8.5.1 dotyczy konkretnie inicjowania agregacji, co powinno oznaczać, że Clang jest prawidłowe do odrzucenia, prawda? Nie tak szybko. 8.5.4/3 mówi:

Lista inicjalizacja obiektu lub odniesienia typu T jest zdefiniowany następująco:

[...]

- w przeciwnym razie, jeśli T jest agregatem, agregat inicjowana jest (8.5.1).

Sądzę, że oznacza to, że obowiązują dokładnie te same zasady, co przy inicjalizacji agregacji, w tym w elewacji, co oznacza, że ​​GCC jest prawidłowe.

Przyznaję, że sformułowanie nie jest szczególnie jasne. A więc, który kompilator ma rację w traktowaniu trzeciego fragmentu? Czy elewacja brasu ma miejsce w inicjalizacji listy, czy nie?

+0

Nicea pytanie! Warto wspomnieć o tym, którego standardu używasz. Standard C++ 11, lub jeśli nie, który konkretny szkic. – juanchopanza

+0

"inicjowanie przydziału" nazywa się inicjowaniem kopii. Wywołuje konstruktora kopiowania, a nie operatora przypisania. – TemplateRex

+0

@TemplateRex: dlatego użyłem pracy "jak". – Fanael

Odpowiedz

20

Klauzula brace ma zastosowanie, ale nie w C++ 11. W C++ 14 będą one stosowane z powodu http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270. Jeśli Ci się poszczęści, Clang skopiuje to do swojego trybu C++ 11 (miejmy nadzieję, że to zrobi!).

+0

Od tej pory 'clang-5.0' w archlinuksie nadal nie obsługuje elity brace nawet z' -std = C++ 17'. –

3

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

W skrócie,

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 
Powiązane problemy