¿Por qué es diferente el comportamiento C ++ initializer_list para std :: vector y std :: array?

Código:

std::vector x{1,2,3,4}; std::array y{{1,2,3,4}}; 

¿Por qué necesito llaves dobles para std :: array?

std::array es un agregado: no tiene constructores declarados por el usuario, ni siquiera uno toma std::initializer_list . La inicialización mediante llaves se realiza mediante la inicialización agregada , una característica de C ++ heredada de C.

El “viejo estilo” de inicialización agregada usa el =

 std::array y = { { 1, 2, 3, 4 } }; 

Con este estilo antiguo de inicialización agregada, se pueden eliminar llaves adicionales, por lo que esto es equivalente a:

 std::array y = { 1, 2, 3, 4 }; 

Sin embargo, estas llaves adicionales solo se pueden elidir “en una statement de la forma T x = { a }; ” (C ++ 11 §8.5.1 / 11), es decir, cuando se usa el estilo antiguo = . Esta regla que permite la elisión del corsé no se aplica a la inicialización directa de la lista. Una nota a pie de página aquí dice: “Las llaves no se pueden elidir en otros usos de inicialización de listas”.

Hay un informe de defectos con respecto a esta restricción: defecto CWG # 1270 . Si se adopta la resolución propuesta, se permitirá la elisión del paréntesis para otras formas de inicialización de la lista, y lo siguiente estará bien formado:

 std::array y{ 1, 2, 3, 4 }; 

(Sombrero de punta a Ville Voutilainen para encontrar el informe de defectos).

Porque std::vector ofrece un constructor que toma std::initializer_list , mientras que std::array no tiene constructores y {1, 2, 3, 4} arriostrados init-list de hecho no se interpreta como std::initializer_list , pero inicialización agregada para la matriz interna de estilo C de std::array (de ahí viene el segundo conjunto de llaves: One para std::array , uno para la matriz de miembros interna C-style).