2011-08-18 9 views
17

std::initializer_list es construido por el compilador desde una lista de inicio incluida en llaves y el tamaño de esta lista debe ser una constante de tiempo de compilación.¿Por qué el tamaño no es un argumento de plantilla de std :: initializer_list?

Entonces, ¿por qué el comité decidió omitir el tamaño de los argumentos de la plantilla? Esto posiblemente evita algunas optimizaciones y hace que algunas cosas sean imposibles (inicializando std::array desde un std::initializer_list).

+4

Una pregunta muy similar es "¿por qué es' std :: :: initializer_list size' no 'constexpr' (más)?" que se preguntó en clC++ m hace un año. – MSalters

+1

Comentario de Re MSalters de 2011, observe que C++ 14 * hace * que 'std :: initializer_list :: size' sea una función' constexpr', aunque C++ 11 no. http://en.cppreference.com/w/cpp/utility/initializer_list/size – Quuxplusone

Respuesta

7

Una ventaja del sistema existente es que puede exportar funciones que toman un initializer_list desde una DLL. Si estuviera modelado en el tamaño, tendrían que enviarse como fuente.

+4

En la misma línea: puede causar una hinchazón no trivial. – MSalters

13

Si initializer_list se definió como std::initializer_list<type, size>, entonces cualquier función que toma uninitializer_list<type>, donde type es algún tipo de concreto, ahora tendría que ser una función de plantilla en función del tamaño de esa lista. O tendrían que requerir que los usuarios pasen un initializer_list de un tipo específico y el tamaño.

Ambos son bastante inaceptables. No todos escriben todos sus códigos como plantillas.

Puede inicializar un std::array desde una lista inicial activada ({} con elementos en el medio). Pero eso no es lo mismo que std::intiializer_list. La clase array es un tipo agregado. Es una estructura que contiene un solo elemento, que es una matriz pública. Por lo tanto, en un conformes C++ 11 implementaciones, esto debe compilar:

std::array<int, 3> myArray = {1, 3, 5}; 

Sin embargo, {1, 3, 5} no es un objeto std::initializer_list; es meramente una lista inicial arrinconada, que se puede usar para inicializar los tipos apropiados.

no se puede pasar un objeto std::initializer_list al constructor de un aggegate (ya que los agregados tienen ningún constructor), pero se puede utilizar un-init-lista arriostrados para invocar inicialización de agregados para inicializar un std::array, tal como lo haría para cualquier estructura que contiene una matriz.

La diferencia entre un std::initializer_list y un braced-init-list es un poco como la diferencia entre un int y el literal 0. No es (por lo general) legal convertir implícitamente un objeto int en un tipo de puntero, pero es legal convertir implícitamente un entero literal 0 en un tipo de puntero. La forma-init-listas apoyadas trabajo es así:

int i = 0; //Legal 
void *j = 0; //Legal 
void *k = i; //Not legal 

std::array<int, 3> myArray = {1, 3, 5};    //Legal 
std::initializer_list<int> myInitList = {1, 3, 5}; //Legal 
std::array<int, 3> myArray = myInitList;   //Not legal 
+0

¿Estás seguro de inicializar 'std :: array' from' std :: initializer_list'? 'array x = {1,2,3}' no funciona en gcc 4.6 y no puedo inferir que esto debería funcionar desde n3242. – pmr

+0

@pmr: std :: array se define (en N3291) como una estructura, y sigue las reglas de C++ 0x para un tipo de agregado. Por lo tanto, debe inicializarse a través de la inicialización agregada. Entonces lo inicializas como si fuera una estructura que contiene una matriz de 3 elementos. Actualizaré mi publicación para explicar esto. –

+1

@Nicol: Eso es solo una inicialización agregada - 'initializer_list' es completamente ortogonal. – ildjarn

Cuestiones relacionadas