2015-02-09 24 views
6

Come posso convertire std :: vector in std :: tuple? HoC++: converte il vettore in tupla

class T { }; 
int cnt = 3; 
vector<T*> tv; 
for (int i = 0; i < cnt; ++i) { 
    tv.push_back(new T()); 
} 

voglio ottenere

auto tp = std::tie(*tv[0], *tv[1], *tv[2]); 

Come posso ottenere questo tp? Se cnt è abbastanza grande, non posso scrivere questo tp manualmente.

std::vector< 
    ConvConnection< 
    decltype(inputLayer), 
    decltype(*C1[0]), 
    decltype(*Conn1Opt[0]), 
    RandomInitialization<arma::mat>, 
    arma::mat 
    >* > Conn1(6); 

    for (size_t i = 0; i < 6; ++i) { 
    Conn1.push_back(new ConvConnection< 
        decltype(inputLayer), 
        decltype(*C1[0]), 
        decltype(*Conn1Opt[0]), 
        RandomInitialization<arma::mat>, 
        arma::mat 
        >(inputLayer, *C1[i], *Conn1Opt[i], 5, 5)); 
    } 

Questo è il codice. Ecco solo 6, ma ho anche bisogno di un vettore con una dimensione superiore a 100. Ho bisogno di convertire questo vettore in una tupla.

+0

Se è troppo grande o ingombrante da scrivere manualmente, scrivere un altro programma che lo genera. Se si desidera determinare la dimensione della tupla in fase di esecuzione, non è possibile. – molbdnilo

+1

Perché hai bisogno di una tupla? Non funzionerebbe 'std :: array '? – dasblinkenlight

+2

Un nitpick off-topic: dovresti avere nomi di variabili/classi migliori. Non c'è motivo per cui 'cnt' non possa essere scritto come' count'. Cos'è un 'ConvConnection'? 'Conn1Opt'? Nel 2015, i tuoi file sorgente rimarranno ancora sul tuo disco rigido con alcuni caratteri in più, e altri sviluppatori che guarderanno il tuo codice ti ringrazieranno più tardi :) – Julian

risposta

7

Non puoi proprio. Poiché la dimensione del vettore è nota al runtime, ma il tipo tuple (che include le sue dimensioni) deve essere noto al momento della compilazione.

+0

Allora come posso ottenere una tupla "grande"? Voglio ottenere auto tp = std :: tie (T1, T2, T3, ..... TN) Supponiamo che N sia abbastanza grande, Devo generare T1 ... TN dinamico. Supponiamo che N sia fisso quando scrivo codice. –

+0

cos'è la tupla "grande"? –

13

Generalmente, non è possibile convertire un vector in un tuple. Tuttavia, se tutti si sta cercando di fare è rendere la tupla <f(0), f(1), ..., f(N-1)> per qualche N che è una costante espressione, allora questo è fattibile con il trucco sequenza di indice:

template <typename F, size_t... Is> 
auto gen_tuple_impl(F func, std::index_sequence<Is...>) { 
    return std::make_tuple(func(Is)...); 
} 

template <size_t N, typename F> 
auto gen_tuple(F func) { 
    return gen_tuple_impl(func, std::make_index_sequence<N>{}); 
} 

che possiamo usare come:

// make a tuple of the first 10 squares: 0, 1, 4, ..., 81 
auto squares = gen_tuple<10>([](size_t i){ return i*i;}); 

Per il vostro specifico caso d'uso, che sarebbe:

auto connections = gen_tuple<6>([&](size_t i) { 
    return new ConvConnection< 
       decltype(inputLayer), 
       decltype(*C1[0]), 
       decltype(*Conn1Opt[0]), 
       RandomInitialization<arma::mat>, 
       arma::mat 
       >(inputLayer, *C1[i], *Conn1Opt[i], 5, 5); 
}); 
+0

Grazie. Ma ho bisogno di tuple dove ogni Ti è una classe. Lo uso per costruire una rete di neuroni. Perché l'attuale framework di NN usa tuple, ma ora la mia rete è troppo grande per poterla scrivere manualmente. Sembra che debba cambiare il framework o generarlo usando un altro programma. –

+0

@HurricaneTong Puoi farlo anche con le lezioni. Basta sostituire 'make_tuple (Is ...)' con 'make_tuple (new T (Is) ...)'. – Barry

+0

Aggiorno la domanda e fornisco il mio codice reale. Ogni classe nella tupla ha parametri diversi per la costruzione. Puoi aiutarmi con questo? –

7

Se si dispone di C++ 14, si può fare in questo modo:

template <typename T, std::size_t... Indices> 
auto vectorToTupleHelper(const std::vector<T>& v, std::index_sequence<Indices...>) { 
    return std::make_tuple(v[Indices]...); 
} 

template <std::size_t N, typename T> 
auto vectorToTuple(const std::vector<T>& v) { 
    assert(v.size() >= N); 
    return vectorToTupleHelper(v, std::make_index_sequence<N>()); 
} 

Grazie alla deduzione automatica, questo è ok. In C++ 11, senza deduzione automatica, è necessario scrivere i tipi restituiti con il trailing decltype. Devi anche implementare il tuo index_sequence.