¿Diferencia entre std :: pair y std :: tuple con solo dos miembros?

92

¿Hay alguna diferencia entre an std::pairy an std::tuplecon solo dos miembros? (Además de lo obvio que std::pairrequiere dos y solo dos miembros y tuplepuede tener más o menos ...)

Casey
fuente

Respuestas:

86

Hay algunas diferencias:

  1. std::tuplenunca puede ser por diseño estándar (al menos, no es requerido por el estándar). Cada std::pair<T, Y>es de diseño estándar si ambos Ty Yson de diseño estándar.

  2. Es un poco más fácil obtener el contenido de pairun tuple. Debe usar una llamada de función en el tuplecaso, mientras que el paircaso es solo un campo miembro.

Pero eso es todo.

Nicol Bolas
fuente
5
"Es un poco más fácil obtener los datos de un par que de una tupla. Un poco". Me di cuenta. : P Aunque .firsty .secondson útiles, no ofrecen ayuda si se requiere un tercer (o más) miembro (s) en un cambio de código. He notado que tiendo a usar std::getindependientemente en cualquier Getter de esa manera, no necesito cambiar todo, solo los tipos de datos y las make_pairllamadas a las make_tuplellamadas.
Casey
Parece que se std::mapusa std::pair<const Key,T>como value_typepar en C ++ 11. ¿Dónde se usan exactamente las tuplas std::map?
nknight
@nknight: ... No tengo idea de por qué dije eso. O lo que quise decir en lugar de std::map.
Nicol Bolas
1
@Yakk: Um, presiono "." y mi IDE muestra una lista de miembros. No pensé que la gente necesitara eso enunciado.
Nicol Bolas
2
Me pregunto si el enlace estructurado en c ++ 17 ya invalida tanto el punto 1 como el 2 de esta respuesta. Si es así, agregue una versión c ++ 17 de esto también.
sandthorn
29

Esta es una respuesta muy tardía, pero tenga en cuenta que, debido a que std::pairse define con variables miembro, su tamaño no se puede optimizar utilizando la optimización de clase base vacía ( firsty seconddebe ocupar direcciones distintas, incluso si una o ambas son clases vacías). Esto se ve agravado por los requisitos de alineación que second_typetenga, por lo que, en el peor de los casos, el resultado std::pairserá básicamente el doble del tamaño que necesita.

std::tuplesolo permite el acceso a través de funciones auxiliares, por lo que es posible que se derive de cualquier tipo si uno u otro está vacío, ahorrando en la sobrecarga. La implementación de GCC, al menos, definitivamente hace esto ... puede revisar los encabezados para verificar esto, pero también hay esto como evidencia.

Stephen Lin
fuente
4
Por supuesto, C ++ 20[[no_unique_address]] debería eliminar std::pairla desventaja.
Deduplicador
"std :: tuple solo permite el acceso a través de funciones auxiliares", o enlaces estructurados de C ++ 17. Es triste que tantas respuestas razonables de C ++ estén tan rápidamente desactualizadas en estos días. :-(
cosimo193
29

El std::tuplenombre de An es más largo (un carácter adicional). Más de esos caracteres se escriben con la mano derecha, por lo que es más fácil para la mayoría de las personas escribir.

Dicho esto, std::pairsolo puede tener dos valores: no cero, uno, tres o más. DOS valores. Una tupla, sin embargo, casi no tiene limitación semántica en el número de valores. An std::pair, por lo tanto, es un tipo seguro de tipo más preciso para usar si realmente desea especificar un par de valores.

Arafangion
fuente
20
Jajaja ¡Genial que consideres cómo está escrito! Sin embargo, me gustaría señalar que probablemente escribo 'par' más de un 20% más rápido que 'tupla'. Esto se debe a que mis manos escriben cada carácter alternativamente, es decir. RHS: p, LHS: a, RHS: i, LHS: r. ¡Al menos para mí me resulta más fácil de hacer! - ¡pero aún obtienes +1!
Richard Corden
15
" Un std :: pair, por lo tanto, es un tipo seguro de tipo más preciso para usar si realmente desea especificar un par de valores " . No es más seguro de tipo o "preciso", solo (posiblemente) indica la intención más directamente.
ildjarn
1
@Arafangion: tambiénstd::tuple<> es de tipo seguro (¿cómo no podría serlo?), Y no es semánticamente diferente a . 2pair
ildjarn
1
" Un std :: par, por lo tanto, es un tipo más preciso y seguro de usar " Y creo que cualquier hablante de inglés pensará en 'par' y 'dos' como completamente sinónimos. : -]
ildjarn
5
@ildjam: Aquí estamos partiendo los pelos, pero no, no son completamente sinónimos. Cuando dice "dos zapatos", ¿quiere decir "Dos zapatos, que bien podrían ser los dos zapatos izquierdos", o quiere decir "Un par de zapatos" (uno de los cuales siempre es el izquierdo y el otro siempre el derecho)? ?
Arafangion
9

Tenga en cuenta que con C ++ 17, se puede usar la misma interfaz para leer datos tanto de pares como de tuplas con dos elementos.

auto [a, b] = FunctionToReturnPairOrTuple();

No es necesario usar get<>:)

bhardwajs
fuente
3

Por lo que vale, encuentro que la salida GDB de std :: tuple es mucho más difícil de leer. Obviamente, si necesita más de 2 valores, std :: pair no funcionará, pero considero que esto es un punto a favor de las estructuras.

tgoodhart
fuente
Por eso, cuando los usé en clases, envuelvo la línea bruta std::get<0>(tupleName)en un captador; GetX()es mucho más fácil de leer y más corto. Tiene una pequeña desventaja de que si se olvida de que sea un constmétodo que alguien puede hacer algo estúpido como esto: GetX() = 20;.
Casey