c++ c++11 language-lawyer brace-initialization aggregate-initialization

c++ - Brace elision en la inicialización std:: array



c++11 language-lawyer (2)

La elisión de Brace se aplica, pero no en C ++ 11. En C ++ 14, se aplicarán debido a http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270 . Si tienes suerte, Clang lo transferirá a su modo C ++ 11 (¡ojalá lo hagan!).

Supongamos que hay una std::array para inicializar. Está bien si usa llaves dobles:

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

También está bien usar llaves simples en la buena inicialización de agregados antiguos, ya que la elisión de abrazadera se ocupará de las llaves faltantes:

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

Sin embargo, ¿está bien utilizar la inicialización de lista con llaves individuales? GCC lo acepta, Clang lo rechaza con "no se pueden omitir llaves alrededor de la inicialización del subobjeto cuando se utiliza la inicialización directa de la lista".

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

La única parte del estándar donde se menciona la elisión de corsé es 8.5.1 / 12, que dice:

Todas las conversiones de tipo implícitas (Cláusula 4) se tienen en cuenta al inicializar el miembro agregado con una expresión de asignación. Si la expresión de asignación puede inicializar un miembro, el miembro se inicializa. De lo contrario, si el miembro es en sí mismo un subaggregado, se supone una elisión de corchete y la expresión de asignación se considera para la inicialización del primer miembro del subaggregado.

8.5.1 se trata de la inicialización agregada específicamente, entonces eso debería significar que Clang es correcto para rechazar, ¿verdad? No tan rapido. 8.5.4 / 3 dice:

La inicialización de lista de un objeto o referencia de tipo T se define de la siguiente manera:

[...]

- De lo contrario, si T es un agregado, se realiza la inicialización agregada (8.5.1).

Creo que significa que se aplican las mismas reglas exactas que con la inicialización agregada, incluida la elisión del paréntesis, lo que significa que GCC acepta correctamente.

Lo admito, la redacción no es particularmente clara. Entonces, ¿qué compilador tiene razón en su tratamiento del tercer fragmento? ¿La elisión del corsé ocurre en la inicialización de la lista, o no?


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

En breve,

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