2010-08-05 21 views
38

Mi chiedo se la tupla può essere inizializzata dall'elenco di inizializzatore (per essere più precisi - da initializer_list di initializer_lists)? Considerando la definizione di parametri:Inizializzazione di std :: tuple dall'elenco di inizializzazione

typedef std::tuple< std::array<short, 3>, 
        std::array<float, 2>, 
        std::array<unsigned char, 4>, 
        std::array<unsigned char, 4> > vertex; 

non v'è alcun modo di fare quanto segue:

static vertex const nullvertex = { {{0, 0, 0}}, 
            {{0.0, 0.0}}, 
            {{0, 0, 0, 0}}, 
            {{0, 0, 0, 0}} }; 

voglio solo raggiungere stessa funzionalità ho ottenuto utilizzando struct invece di tuple (quindi solo gli array vengono inizializzati per initializer_list):

static struct vertex { 
    std::array<short, 3> m_vertex_coords; 
    std::array<float, 2> m_texture_coords; 
    std::array<unsigned char, 4> m_color_1; 
    std::array<unsigned char, 4> m_color_2; 
} const nullvertex = { 
    {{0, 0, 0}}, 
    {{0.0, 0.0}}, 
    {{0, 0, 0, 0}}, 
    {{0, 0, 0, 0}} 
}; 

v'è alcun motivo devo usare tuple, chiedo solo. Lo sto chiedendo, perché non sono in grado di esaminare gli errori dei modelli g ++ generati dal mio tentativo di inizializzare questa tupla.

@Motti: così ho perso la sintassi corretta per l'inizializzazione uniforme -

static vertex const nullvertex = vertex{ {{0, 0, 0}}, 
             {{0.0, 0.0}}, 
             {{0, 0, 0, 0}}, 
             {{0, 0, 0, 0}} }; 

e

static vertex const nullvertex{ {{0, 0, 0}}, 
           {{0.0, 0.0}}, 
           {{0, 0, 0, 0}}, 
           {{0, 0, 0, 0}} }; 

Ma sembra che tutti i problemi si trova in array, che ha ottenuto nessun costruttore per initializer_list e avvolgere gli array con un vero costruttore non sembra un compito così facile.

risposta

40

Gli elenchi di inizializzatori non sono rilevanti per le tuple.

Penso che stai confondendo due diversi usi di parentesi graffe in C++ 0x.

  1. initializer_list<T> è una raccolta omogenea (tutti i membri devono essere dello stesso tipo, quindi non rilevante per std::tuple)
  2. Uniform initialization è dove parentesi graffe sono usate per costruire una varietà di oggetti; matrici, POD e classi con costruttori. Il che ha anche il vantaggio di risolvere the most vexing parse)

Ecco una versione semplificata:

std::tuple<int, char> t = { 1, '1' }; 
// error: converting to 'std::tuple<int, char>' from initializer list would use 
// explicit constructor 'std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) 
// [with _U1 = int, _U2 = char, _T1 = int, _T2 = char]' 

std::tuple<int, char> t { 1, '1' }; // note no assignment 
// OK, but not an initializer list, uniform initialization 

Il messaggio di errore dice è che si sta cercando di chiamare implicitamente il costruttore ma è un costruttore esplicito in modo da poter 't.

Fondamentalmente quello che stai cercando di fare è qualcosa di simile:

struct A { 
    explicit A(int) {} 
}; 

A a0 = 3; 
// Error: conversion from 'int' to non-scalar type 'A' requested 

A a1 = {3}; 
// Error: converting to 'const A' from initializer list would use 
// explicit constructor 'A::A(int)' 

A a2(3); // OK C++98 style 
A a3{3}; // OK C++0x Uniform initialization 
+0

Grazie per la risposta! – erjot

+5

Perché la costruzione di una 'std :: tuple' con una lista di init rinforzata è una cosa brutta? Funziona per 'std :: pair's, e' std :: tuple' è la generalizzazione 'std :: pair', quindi non capisco il motivo di questa limitazione: S ... – rubenvb

+4

@rubenvb è OK inizializzare una 'tupla' con inizializzazione uniforme (parentesi graffe) ma per farlo è necessario eliminare il segno di uguale. Se si dispone di un segno di uguale, significa che si costruisce un temporaneo con il costruttore di un parametro che accetta un elenco di inizializzazione e quindi si utilizza il costruttore di copie dal valore temporaneo (sebbene il compilatore possa elidere parte di questo). – Motti

Problemi correlati