Domanda

Perché nessuno sembra usare le tuple in C++, il Boost Tupla Biblioteca o la libreria standard per TR1?Ho letto un sacco di codice di C++, e molto raramente faccio a vedere l'uso di tuple, ma mi capita spesso di vedere un sacco di posti dove tuple avrebbe risolto molti problemi (di solito la restituzione di valori multipli di funzioni).

Tuple permetterà di fare tutti i tipi di cose interessanti come questa:

tie(a,b) = make_tuple(b,a); //swap a and b

Che è sicuramente meglio di questo:

temp=a;
a=b;
b=temp;

Naturalmente si può sempre fare questo:

swap(a,b);

Ma cosa succede se si desidera ruotare tre valori?Si può fare questo con tuple:

tie(a,b,c) = make_tuple(b,c,a);

Tuple anche rendere molto più facile per tornare più variabile da una funzione, che è probabilmente molto più comune caso di scambio di valori.Utilizzando i riferimenti a valori di ritorno non è certamente molto elegante.

Ci sono grandi svantaggi per le tuple in cui riesco a non pensare?Se no, perché sono raramente utilizzati?Sono più lente?O è solo che le persone non sono abituati a loro?È una buona idea di utilizzare le tuple?

È stato utile?

Soluzione

Perché non è ancora standard. Tutto ciò non standard ha un ostacolo molto più alto. Pezzi di Boost sono diventati popolari perché i programmatori chiedevano a gran voce per loro. (Hash_map salta in mente). Ma mentre tuple è a portata di mano, non è una tale vittoria schiacciante e chiaro che le persone si preoccupano con esso.

Altri suggerimenti

Una risposta cinica è che molte persone programma in C ++, ma non capisco e / o utilizzare la funzionalità di livello superiore. A volte è perché non sono permessi, ma molti semplicemente non cercano (o anche capire).

Come esempio non-boost: quante persone utilizzano la funzionalità si trovano in <algorithm>

In altre parole, molti programmatori C ++ sono semplicemente i programmatori C che utilizzano i compilatori C ++, e forse std::vector e std::list. Questa è una ragione per cui l'uso di boost::tuple non è più comune.

La sintassi tupla C ++ può essere un po 'più dettagliata di quanto la maggior parte delle persone vorrebbe.

Si consideri:

typedef boost::tuple<MyClass1,MyClass2,MyClass3> MyTuple;

Quindi, se si vuole fare un uso estensivo di tuple potrete trovare o typedef tuple ovunque o si ottiene fastidiosamente nomi di tipo lunghi ovunque. Mi piace tuple. Li uso quando necessario. Ma è solitamente limitato a un paio di situazioni, come un indice N-elemento o quando si utilizza multimaps per legare le coppie gamma iteratori. Ed è di solito in un ambito molto limitato.

E 'tutto molto brutto e hacky cercando rispetto a qualcosa come Haskell o Python. Quando C ++ 0x arriva qui e otteniamo le tuple parola chiave 'auto' cominceranno a guardare molto più attraente.

L'utilità di tuple è inversamente proporzionale al numero di tasti necessari per dichiarare, confezione, e decomprimerli.

Per quanto mi riguarda, è l'abitudine, giù le mani: Le tuple non risolve alcun nuovi problemi per me, solo alcuni Posso già gestire bene. Scambiare i valori si sente ancora più facile alla vecchia maniera - e, cosa più importante, non ho davvero pensare a come scambiare "meglio". E 'abbastanza buono così com'è.

Personalmente, non credo che le tuple sono una grande soluzione per la restituzione di valori multipli -. Suona come un lavoro per struct s

Ma cosa succede se si desidera ruotare tre valori?

swap(a,b);
swap(b,c);  // I knew those permutation theory lectures would come in handy.

OK, quindi con valori 4, ecc, alla fine il n-pla diventa meno codice di n-1 swap. E con questo default swap fa 6 assegnazioni invece dei 4 si avrebbe se è stato implementato un modello in tre cicli da soli, anche se mi auguro che il compilatore avrebbe risolto che per i tipi semplici.

Si può venire con scenari in cui gli swap sono ingombranti o inappropriati, ad esempio:

tie(a,b,c) = make_tuple(b*c,a*c,a*b);

è un po 'imbarazzante per decomprimere.

Il punto è, modi però, ci sono noti di affrontare le situazioni più comuni che le tuple sono buoni per, e quindi senza grande urgenza a prendere le tuple. Se non altro, io non sono sicuro che:

tie(a,b,c) = make_tuple(b,c,a);

non fa 6 copie, il che rende del tutto inadatto per alcuni tipi (collezioni di essere la più ovvia). Sentitevi liberi di persuadermi che tuple sono una buona idea per i "grandi" tipi, col dire che questo non è così: -)

Per la restituzione di valori multipli, tuple sono perfetti se i valori sono di tipi incompatibili, ma alcune persone non piace loro se è possibile per il chiamante per farli nell'ordine sbagliato. Alcune persone non amano più valori di ritorno a tutti, e non vogliono incoraggiare il loro utilizzo da parte rendendoli più facili. Alcune persone semplicemente preferiscono strutture che prendono il nome dentro e fuori dei parametri, e probabilmente non poteva essere persuasi con una mazza da baseball da utilizzare tuple. I gusti sono gusti.

Come molti hanno sottolineato, tuple non sono solo che utile come altre caratteristiche.

  1. Lo scambio ed espedienti rotanti sono solo espedienti. Sono assolutamente fonte di confusione per coloro che non li hanno mai visto prima, e dal momento che è più o meno tutti, questi espedienti sono solo poveri pratica dell'ingegneria del software.

  2. Tornando valori multipli utilizzando tuple è molto meno di auto-documenta poi le alternative - ritorno tipi di nome o utilizzando i riferimenti di nome. Senza questa auto-documentazione, è facile confondere l'ordine dei valori restituiti, se sono reciprocamente convertibili, e non essere più saggio.

Non tutti possono usare boost, e TR1 non è ancora ampiamente disponibili.

Quando si utilizza C++ su sistemi embedded, tirando in librerie Boost diventa complesso.Si accoppiano tra loro, in modo biblioteca aumenta di dimensioni.Si torna strutture di dati o utilizzare il parametro che passa invece di tuple.Quando la restituzione di tuple in Python la struttura dati è l'ordine e il tipo dei valori restituiti solo che non esplicita.

Si vede raramente li perché il codice ben progettato di solito non ha bisogno di loro- non ci sono molti casi in libertà in cui si utilizza uno struct anonimo è superiore all'utilizzo di un nome uno. Poiché tutti una tupla rappresenta davvero è una struct anonima, la maggior parte dei programmatori nella maggior parte delle situazioni basta andare con la cosa reale.

Supponiamo di avere una funzione di "f" in cui un ritorno tupla potrebbe avere un senso. Come regola generale, tali funzioni sono di solito abbastanza complicato che possono fallire.

Se "f" può fallire, è necessario un Return- di stato, dopo tutto, non si desidera che i chiamanti devono ispezionare ogni parametro per rilevare il fallimento. "F" probabilmente si inserisce nel modello:

struct ReturnInts ( int y,z; }
bool f(int x, ReturnInts& vals);

int x = 0;
ReturnInts vals;
if(!f(x, vals)) {
    ..report error..
    ..error handling/return...
}

Non è abbastanza, ma un'occhiata a come brutto l'alternativa è. Si noti che ho ancora bisogno di un valore di stato, ma il codice non più leggibile e non più breve è. Probabilmente è più lento, in quanto anche io sostenere il costo di 1 copia con la tupla.

std::tuple<int, int, bool> f(int x);
int x = 0;
std::tuple<int, int, bool> result = f(x); // or "auto result = f(x)"
if(!result.get<2>()) {
    ... report error, error handling ...
}

Un altro, aspetto negativo significativo è nascosto nella qui- con "ReturnInts" Posso aggiungere alter 's ritorno modificando 'ReturnInts' senza alterare 'f'' "f" s INTERFACCIA. La soluzione tupla non offre questa funzione critica, che lo rende la risposta inferiore per qualsiasi codice della libreria.

Certamente tuple possono essere utili, ma come detto c'è un po 'di testa e un ostacolo o due si deve saltare attraverso prima di poter anche realmente usarli.

Se il programma trova costantemente i luoghi in cui è necessario restituire più valori o di swap più valori, forse vale la pena di andare il percorso tupla, ma per il resto a volte è solo più facile da fare le cose nel modo classico.

In linea generale, non tutti ha già installato Boost, e certamente non sarebbe passare attraverso la seccatura di scaricare e configurare il mio includere le directory di lavorare con essa solo per le sue strutture tuple. Penso che troverete che le persone che già utilizzano Boost hanno più probabilità di trovare tupla utilizza nei loro programmi che gli utenti non-Boost, e immigrati provenienti da altre lingue (Python viene in mente) hanno maggiori probabilità di essere semplicemente sconvolto per la mancanza di tuple in C ++ che per esplorare metodi di aggiungere il supporto tuple.

Come un data-store std::tuple presenta le caratteristiche peggiori di entrambi un struct e un array; tutti gli accessi si basa posizione n ma non si può scorrere un tuple utilizzando un for ciclo.

Quindi, se gli elementi della a.lastname sono concettualmente un array, userò una matrice e se gli elementi non sono concettualmente un array, una struttura (che ha nominato gli elementi) è più gestibile. (std::get<1>(a) è più esplicativo di <=>).

Questo lascia la trasformazione menzionato dalla OP come l'unico caso d'uso praticabile per tuple.

Ho la sensazione che molti usano Boost.Any e Boost.Variant (con un po 'di ingegneria), invece di Boost.Tuple.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top