2015-03-19 14 views
7

Ho il codice seguente:inizializzazione std :: matrice aggregata richiede una quantità di confusione di graffe

enum class MessageDeliveryMethod 
    { 
     POST_MASTER, 
     BUBBLE, 

     NUM_ENUMERATORS 
    }; 

    namespace 
    { 
     using MapType = std::array< 
     std::pair<char const*, MessageDeliveryMethod>, 
     static_cast<std::size_t>(MessageDeliveryMethod::NUM_ENUMERATORS) 
     >; 

     MapType g_mapping = {{ 
     {"POST_MASTER", MessageDeliveryMethod::POST_MASTER}, 
     {"BUBBLE", MessageDeliveryMethod::BUBBLE}, 
     }}; 
    } 

Questa compila ma non so perché. La variabile g_mapping richiede un livello aggiuntivo di parentesi graffe apparentemente ridondanti. In altre parole, mi aspetto che l'inizializzazione sia simile a:

MapType g_mapping = { 
    {"POST_MASTER", MessageDeliveryMethod::POST_MASTER}, 
    {"BUBBLE", MessageDeliveryMethod::BUBBLE}, 
}; 

(Un livello di parentesi graffe rimosso).

La mia comprensione è che prima di C++ 14, quando si esegue l'inizializzazione diretta è richiesto il livello aggiuntivo di parentesi. Tuttavia, l'inizializzazione della copia non avrebbe dovuto richiedere questo basato su this page (guarda l'esempio lì).

Qualcuno può spiegarlo?

UPDATE:

This SO question che si presume essere duplicato dalla mia domanda in effetti rispondere ad alcune domande specifiche e utili (in relazione alla mia) ma fuori contesto il mio era confusa a causa dell'utilizzo di pair (che ho il pensiero stava causando inizialmente il problema). Non avrei mai trovato quella domanda SO in primo luogo, quindi se mai penso che il modo in cui ho formulato la mia domanda possa aiutare le persone ad arrivare alla soluzione da diverse angolazioni.

+0

Plusone per il titolo. La coppia elision è davvero una ... disabbia? –

+0

Ho modificato il mio post per chiarire perché non ritengo che sia un duplicato. I moderatori/comunità SO sono diventati pessimi ultimamente riguardo alla chiusura prematura delle domande come duplicati invece di considerare le prospettive di tutti gli altri. –

+0

Arrivando da diverse angolazioni è lo scopo di mantenere le domande duplicate sul sito. Non è un problema che questo porti a risposte esistenti. –

risposta

5

std::array è definito come una struttura che contiene una matrice.

Quindi la prima coppia di parentesi graffe viene utilizzata per inizializzare i membri dati della struttura che è l'array. La seconda coppia di parentesi graffe viene utilizzata per inizializzare la matrice all'interno della struttura. E la terza coppia di parentesi graffe viene utilizzata per inizializzare ogni oggetto di tipo std :: pair.

Per essere più precisi poi secondo standard C++ (23.3.2.1 Classe panoramica template matrice)

2 Un array è un aggregato (8.5.1) che può essere inizializzato con la sintassi

array<T, N> a = { initializer-list }; 

dove inizializzatore-list è un elenco separato da virgole di fino a N elementi cui tipi sono convertibili a T.

+0

Grazie, ha senso. Questo sembra un problema di progettazione di 'std :: array' allora. Suggerirei che potrebbe essere risolto semplicemente fornendo un sovraccarico costruttore per 'std :: initializer_list', ma ciò renderebbe un tipo non aggregato come richiesto. Non sei sicuro di quale sia la soluzione, ma è un po 'scomodo da usare come adesso. –

0

Nello standard abbiamo 23.3.2.1 (3)

Una matrice è un aggregato (8.5.1) che può essere inizializzato con la sintassi

array<T, N> a = { initializer-list };

Questo mostra che quando si inizializza la matrice con un elenco internalizzatore è necessario avvolgerla in parentesi graffe.

+2

"dove * initializer-list * è un elenco separato da virgola di un massimo di N elementi i cui tipi sono convertibili in T." –

1

std::array viene definito come aggregato nidificato, una classe contenente un array come unico membro.Prima di C++ 14, l'inizializzazione degli aggregati aveva bisogno di due livelli di parentesi: uno per circondare l'elenco dei membri della classe (in cui c'era solo un membro, l'array) e uno per circondare l'elenco degli elementi della matrice. Allora hai bisogno di un terzo livello se, come qui, vuoi elencare-inizializza ogni elemento dell'array.

C++ 14 consente di "appiattire" gli elenchi durante l'inizializzazione di aggregati nidificati, come descritto nella pagina a cui si fa il collegamento.

+0

'std :: pair' non è un aggregato. –

+1

@remyabel: No, non lo è; ma può ancora essere inizializzato in lista. Stavo descrivendo il motivo per cui hai bisogno dei due livelli esterni di parentesi graffe, non quelli attorno a ciascun inizializzatore di 'coppia'. –

+0

Esistono molti duplicati su std :: array che richiede due set di parentesi, ma in questo specifico scenario non è possibile omettere alcuna parentesi. –

Problemi correlati