Différence entre std :: pair et std :: tuple avec seulement deux membres?

92

Y a-t-il une différence entre un std::pairet un std::tupleavec seulement deux membres? (Outre l'évidence qui std::pairnécessite deux et seulement deux membres et tuplepeut avoir plus ou moins ...)

Casey
la source

Réponses:

86

Il y a quelques différences:

  1. std::tuplene peut jamais être par mise en page standard (du moins, il n'est pas nécessaire que ce soit par la norme). Chacun std::pair<T, Y>est une disposition standard si les deux Tet Ysont une disposition standard.

  2. Il est un peu plus facile d'obtenir le contenu d'un pairfichier tuple. Vous devez utiliser un appel de fonction dans le tuplecas, alors que le paircas n'est qu'un champ membre.

Mais c'est à peu près tout.

Nicol Bolas
la source
5
"Il est un peu plus facile d'extraire les données d'une paire que d'un tuple. Un peu." J'ai remarqué. : P Bien .firstet .secondsont à portée de main, ils offrent aucune aide si un membre tiers (ou plus) (s) sont nécessaires dans un changement de code. J'ai remarqué que j'ai tendance à utiliser std::getn'importe quel Getters de cette façon, je n'ai pas besoin de tout changer, juste les types de données et les make_pairappels aux make_tupleappels.
Casey
Il semble que les std::maputilise std::pair<const Key,T>comme value_typemême dans C ++ 11. Où exactement les tuples sont-ils utilisés std::map?
nknight
@nknight: ... Je ne sais pas pourquoi j'ai dit ça. Ou ce que je voulais dire au lieu de std::map.
Nicol Bolas
1
@Yakk: Euh, j'appuie sur "." et mon IDE fait apparaître une liste de membres. Je ne pensais pas que les gens avaient besoin de cela.
Nicol Bolas le
2
Je me demande si la liaison structurée en C ++ 17 invalide déjà à la fois 1 et 2 points de cette réponse? Si tel est le cas, veuillez également en ajouter une version c ++ 17.
sandthorn
29

C'est une réponse très tardive, mais notez que, étant donné qu'elle std::pairest définie avec des variables membres, sa taille ne peut pas être optimisée à l'aide de l' optimisation de classe de base vide ( firstet seconddoit occuper des adresses distinctes, même si l'une ou les deux sont une classe vide). Ceci est exacerbé par les exigences d'alignement second_type, donc dans le pire des cas, le résultat std::pairsera fondamentalement deux fois la taille nécessaire.

std::tuplen'autorise l'accès que via des fonctions d'assistance, il est donc possible qu'il dérive de l'un ou l'autre type si l'un ou l'autre est vide, ce qui économise la surcharge. L'implémentation de GCC, au moins, fait définitivement cela ... vous pouvez parcourir les en-têtes pour vérifier cela, mais il y a aussi cela comme preuve.

Stephen Lin
la source
4
Bien sûr, C ++ 20[[no_unique_address]] devrait supprimer std::pairl'inconvénient de.
Deduplicator
"std :: tuple n'autorise l'accès qu'à travers des fonctions d'assistance", ou des liaisons structurées C ++ 17. Triste que tant de réponses C ++ raisonnables soient si rapidement obsolètes de nos jours. :-(
cosimo193
29

Un std::tuplenom de plus est (un caractère supplémentaire). Plus de ces caractères sont tapés avec la main droite, donc plus faciles à saisir pour la plupart des gens.

Cela dit, std::pairne peut avoir que deux valeurs - pas zéro, une, trois ou plus. DEUX valeurs. Un tuple, cependant, n'a presque aucune limitation sémantique sur le nombre de valeurs. Un std::pair, par conséquent, est un type sécurisé de type plus précis à utiliser si vous souhaitez réellement spécifier une paire de valeurs.

Arafangion
la source
20
LOL! Génial que vous considérez comment il est tapé! Je tiens à souligner cependant que je tape probablement «paire» plus de 20% plus vite que «tuple». C'est parce que mes mains tapent chaque caractère alternativement, c'est-à-dire. RHS: p, LHS: a, RHS: i, LHS: r. Au moins pour moi, je trouve cela plus facile à faire! - mais vous obtenez toujours +1!
Richard Corden
15
" Un std :: pair, par conséquent, est un type sûr de type plus précis à utiliser si vous voulez réellement spécifier une paire de valeurs. " Ce n'est pas plus sûr de type ou "précis", il signale seulement (sans doute) l'intention plus directement.
ildjarn
1
@Arafangion: std::tuple<>est également de type sécurisé (comment pourrait-il ne pas l'être?), Et 2n'est pas sémantiquement différent de pair.
ildjarn
1
" Un std :: pair, par conséquent, est un type plus précis et sûr à utiliser. " Et je pense que tout anglophone pensera que "pair" et "two" sont tout à fait synonymes. : -]
ildjarn
5
@ildjam: Nous nous fendons les cheveux ici, mais non, ils ne sont pas complètement synonymes. Lorsque vous dites «deux chaussures», voulez-vous dire «deux chaussures, qui pourraient bien être les deux chaussures de gauche», ou voulez-vous dire «une paire de chaussures» (dont l'une est toujours à gauche et l'autre qui est toujours à droite) ?
Arafangion
9

Notez qu'avec C ++ 17, on peut utiliser la même interface pour lire les données de la paire et du tuple avec deux éléments.

auto [a, b] = FunctionToReturnPairOrTuple();

Pas besoin d'utiliser get<>:)

bhardwajs
la source
3

Pour ce que ça vaut, je trouve que la sortie GDB de std :: tuple est beaucoup plus difficile à lire. Évidemment, si vous avez besoin de plus de 2 valeurs, std :: pair ne fonctionnera pas, mais je considère que c'est un point en faveur des structs.

tgoodhart
la source
C'est pourquoi, lorsque je les utilise dans les classes, j'emballe la ligne brute std::get<0>(tupleName)dans un getter; GetX()est beaucoup plus facile à lire et plus court. Il a un petit inconvénient que si vous oubliez de le faire une constpersonne de méthode peut faire quelque chose de stupide comme ceci: GetX() = 20;.
Casey