2014-06-08 8 views
6

dicono che sono l'inizializzazione di un vector<vector<string>> in questo modo:Unisci vettore e lista_inizializzazione nell'inizializzazione del vettore <vector<T>>?

vector<vector<string>> v; 
v = {{ 
    {"a", "b", "c"}, 
    {"aa", "bb"}, 
    {"xyz", "yzx", "zxy"}, 
    {} 
}}; 

Supponiamo ora voglio aggiungere un già esistente vector<string> ad alcuni degli elementi v s'. In questo modo:

vector<string> suffix {{"1", "2", "3"}}; 
vector<vector<string>> v; 
v = {{ 
    {"a", "b", "c"} + suffix, 
    {"aa", "bb"}, 
    {"xyz", "yzx", "zxy"} + suffix, 
    {} 
}}; 

Che sintassi, ovviamente, non funziona perché operator+ non è definito in modo tale.

Capisco che è possibile costruire v il primo modo e poi scrivere

vector<int> indices = {0, 2}; 
for(int i: indices) 
    v[i].insert(v[i].end(), suffix.begin(), suffix.end()); 

ma questo non è conveniente perché io possa avere diverse suffix vettori che sono attaccati arbitrariamente v[i]. Voglio che lo suffix sia associato all'inizializzazione di v[i], quindi ha senso e non devo spostare gli indici se aggiungo/rimuovo gli elementi dall'inizializzazione di v.

risposta

3

Una possibile soluzione consiste nell'utilizzare una funzione di supporto che esegue l'aggiunta.

vector<string> appendStrings(vector<string>&& s1, vector<string> const& s2) 
{ 
    s1.insert(s1.end(), s2.begin(), s2.end()); 
    return s1; 
} 

E usarlo per inizializzare la variabile.

vector<string> suffix {{"1", "2", "3"}}; 
vector<vector<string>> v = {{ 
    appendStrings({"a", "b", "c"}, suffix), 
    {"aa", "bb"}, 
    appendStrings({"xyz", "yzx", "zxy"}, suffix), 
    {} 
}}; 

Aggiornamento

una più efficace attuazione della appendStrings (Grazie a @Yakk):

vector<string> appendStrings(initializer_list<char const*>&& s1, 
          vector<string> const& s2) 
{ 
    vector<string> ret. 
    ret.reserve(s1.size() + s2.size()); 
    for (auto item : s1) { 
     ret.emplace_back(item); 
    } 
    ret.insert(ret.end(), s2.begin(), s2.end()); 
    return ret; 
} 
+0

Se 's1' è una lista di inizializzazione, evitare un'allocazione. Se ti muovi, ritorna, evita un altro. – Yakk

+0

@Yakk, penso di aver capito la parte di ritorno 'move' ma non ho idea di cosa intendi per la prima parte del tuo commento. –

+0

Cambia 'vector &&' a 'std :: initializer_list ' (o 'T'). Crea un 'vector' entro quel' reserve' abbastanza per detto list e 2nd 'vector', quindi caricalo e torna indietro. Ottieni 1 allocazione di memoria, più 1 per 'std :: string' assegnato, invece del tuo ... 3? più 2 per 'std :: string' (' move' lo abbandona a 2 + 1). Solo microottimizzazione. – Yakk

Problemi correlati