2011-08-18 10 views
17

std::initializer_list viene creato dal compilatore da una lista init racchiusa tra parentesi e la dimensione di questa lista deve essere una costante di tempo di compilazione.Perché la dimensione non è un argomento modello di std :: initializer_list?

Quindi, perché il comitato ha deciso di omettere la dimensione dagli argomenti del modello? Questo probabilmente impedisce alcune ottimizzazioni e rende alcune cose impossibili (inizializzando std::array da un std::initializer_list).

+4

Una domanda molto simile è "perché è' std :: :: initializer_list size' non 'constexpr' (più)?" che è stato chiesto a clC++ m un anno fa. – MSalters

+1

Nel commento di Re MSalters del 2011, si noti che C++ 14 * fa * funzione 'std :: initializer_list :: size' a' constexpr', anche se C++ 11 no. http://en.cppreference.com/w/cpp/utility/initializer_list/size – Quuxplusone

risposta

7

Un lato positivo del sistema esistente è che è possibile esportare le funzioni che prendono uno initializer_list da una DLL. Se fosse modellato sulla dimensione, dovrebbero essere spediti come fonte.

+4

Sulla stessa falsariga: può causare un rigonfiamento non banale. – MSalters

13

Se initializer_list è stata definita come std::initializer_list<type, size>, quindi qualsiasi funzione che prende un initializer_list<type>, dove type è un certo tipo di cemento, sarebbe ora deve essere una funzione template in base alle dimensioni di quella lista. O dovrebbero richiedere che gli utenti passino un initializer_list di un tipo specifico e la dimensione.

Entrambe queste sono piuttosto inaccettabili. Non tutti scrivono tutto il loro codice come modelli.

È possibile inizializzare uno std::array da un elenco di controventi ({} con elementi nel mezzo). Ma non è la stessa cosa di std::intiializer_list. La classe array è un tipo aggregato. È una struttura che contiene un singolo elemento, che è un array pubblico. Pertanto, sulla conformi C++ 11 implementazioni, questo dovrebbe compilare:

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

Tuttavia, {1, 3, 5} non è un oggetto std::initializer_list; è semplicemente una lista di init rinforzata, che può essere usata per inizializzare i tipi appropriati.

Non è possibile passare un oggetto std::initializer_list al costruttore di un aggegate (perché gli aggregati non hanno costruttori), ma è possibile utilizzare un-init-list rinforzato per richiamare l'inizializzazione di aggregazione per inizializzare un std::array, proprio come si farebbe per qualsiasi struct contenente una matrice.

La differenza tra uno std::initializer_list e un bretelle-init-list è un po 'come la differenza tra unoe il valore letterale 0. Non è (di norma) legale convertire implicitamente un oggetto int in un tipo di puntatore, ma è legale convertire implicitamente un numero intero letterale 0 in un tipo di puntatore. Il modo in-init-list imbracciò il lavoro è così:

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

Sei sicuro di inizializzare 'std :: array' da' std :: initializer_list'? 'array x = {1,2,3}' non funziona su gcc 4.6 e non posso dedurre che questo dovrebbe funzionare da n3242. – pmr

+0

@pmr: std :: array è definito (in N3291) come struct e segue le regole C++ 0x per un tipo aggregato. Pertanto, dovrebbe essere inizializzato tramite l'inizializzazione aggregata. Quindi lo inizializzi come se fosse una struttura che contiene un array di 3 elementi. Aggiornerò il mio post per spiegarlo. –

+1

@Nicol: Questa è solo un'inizializzazione aggregata - 'initializer_list' è completamente ortogonale. – ildjarn

Problemi correlati