Diferença entre std :: pair e std :: tuple com apenas dois membros?

95

Existe uma diferença entre um std::paire um std::tuplecom apenas dois membros? (Além do óbvio que std::pairrequer dois e apenas dois membros e tuplepode ter mais ou menos ...)

Casey
fonte

Respostas:

91

Existem algumas diferenças:

  1. std::tuplenão é exigido pelo padrão para ser um layout padrão . Cada um std::pair<T, Y>é de layout padrão se ambos Te Ysão de layout padrão.

  2. É um pouco mais fácil obter o conteúdo de a do pairque de a tuple. Você tem que usar uma chamada de função no tuplecaso, enquanto o paircaso é apenas um campo de membro.

Mas é isso aí.

Nicol Bolas
fonte
5
"É um pouco mais fácil obter os dados de um par do que de uma tupla. Um pouco." Percebi. : P Embora .firste .secondsejam úteis, eles não oferecem nenhuma ajuda se um terceiro (ou mais) membro (s) forem necessários para uma mudança de código. Percebi que tenho tendência a usar std::getindependentemente em qualquer Getters, dessa forma, não preciso alterar tudo, apenas os tipos de dados e quaisquer make_pairchamadas para make_tuplechamadas.
Casey
Parece que std::mapusa std::pair<const Key,T>como value_typemesmo em C ++ 11. Onde exatamente as tuplas são usadas std::map?
nknight 01 de
@nknight: ... Não tenho ideia de por que disse isso. Ou o que eu quis dizer em vez de std::map.
Nicol Bolas
1
@Yakk: Hum, eu pressiono "." e meu IDE traz uma lista de membros. Eu não achei que as pessoas precisassem disso explicado.
Nicol Bolas
2
Eu me pergunto se a vinculação estruturada em c ++ 17 já invalida 1 e 2 pontos desta resposta? Em caso afirmativo, adicione uma versão c ++ 17 disso também.
sandthorn
33

O std::tuplenome de um é mais longo (um caractere extra). Mais desses caracteres são digitados com a mão direita, portanto, mais fáceis para a maioria das pessoas digitar.

Dito isso, std::pairpode ter apenas dois valores - não zero, um, três ou mais. DOIS valores. Uma tupla, entretanto, quase não tem limitação semântica no número de valores. Um std::pair, portanto, é um tipo de tipo seguro mais preciso a ser usado se você realmente deseja especificar um par de valores.

Arafangion
fonte
20
RI MUITO! Brilhante que você considera como está digitado! Gostaria de salientar que provavelmente digito 'par' mais de 20% mais rápido do que 'tupla'. Isso ocorre porque minhas mãos digitam cada caractere alternativamente, ou seja. RHS: p, LHS: a, RHS: i, LHS: r. Pelo menos para mim acho isso mais fácil de fazer! - mas você ainda ganha +1!
Richard Corden
16
" Um std :: pair, portanto, é um tipo seguro de tipo mais preciso para usar se você realmente deseja especificar um par de valores. " Não é mais seguro para o tipo ou "preciso", ele apenas (indiscutivelmente) sinaliza a intenção mais diretamente.
ildjarn 01 de
1
@Arafangion: tambémstd::tuple<> é seguro para tipos (como não poderia ser?) E não é semanticamente diferente de . 2pair
ildjarn
1
" Um std :: pair, portanto, é um tipo mais preciso e seguro de usar " E acho que qualquer falante de inglês pensará em 'pair' e 'two' como sinônimos. : -]
ildjarn
5
@ildjam: Estamos dividindo cabelos aqui, mas não, eles não são completamente sinônimos. Quando você diz "dois sapatos", quer dizer "dois sapatos, que podem ser os dois sapatos esquerdos", ou "Um par de sapatos" (um dos quais é sempre esquerdo e o outro sempre direito) ?
Arafangion
31

Esta é uma resposta muito tardia, mas observe que, por std::pairser definido com variáveis ​​de membro, seu tamanho não pode ser otimizado usando a otimização de classe base vazia ( firste seconddeve ocupar endereços distintos, mesmo se uma ou ambas forem uma classe vazia). Isso é exacerbado por quaisquer requisitos de alinhamento second_type, portanto, no pior caso, o resultado std::pairserá basicamente o dobro do tamanho que precisa ser.

std::tuplesó permite acesso por meio de funções auxiliares, portanto, é possível derivar de qualquer tipo se um ou outro estiver vazio, economizando na sobrecarga. A implementação do GCC, pelo menos, definitivamente faz isso ... você pode vasculhar os cabeçalhos para verificar isso, mas também há isso como evidência.

Stephen Lin
fonte
4
Claro, C ++ 20[[no_unique_address]] deve remover std::paira desvantagem de.
Deduplicator de
"std :: tuple só permite acesso por meio de funções auxiliares" ou ligações estruturadas C ++ 17. É triste que tantas respostas razoáveis ​​em C ++ estejam tão rapidamente desatualizadas hoje em dia. :-(
cosimo193
11

Observe que, com C ++ 17, pode-se usar a mesma interface para ler dados de pares e tuplas com dois elementos.

auto [a, b] = FunctionToReturnPairOrTuple();

Não há necessidade de usar get<>:)

Bhardwajs
fonte
3

Pelo que vale a pena, acho que a saída do GDB de std :: tuple é muito mais difícil de ler. Obviamente, se você precisar de mais de 2 valores, std :: pair não funcionará, mas eu considero isso um ponto a favor de structs.

tgoodhart
fonte
É por isso que, quando os uso nas aulas, envolvo a linha grossa std::get<0>(tupleName)em um getter; GetX()é muito mais fácil de ler e mais curto. Ele tem uma pequena desvantagem que se você se esqueça de torná-lo um constalguém método pode fazer algo estúpido assim: GetX() = 20;.
Casey