Pergunta

Como a maioria dos programadores que eu admiro e tentar seguir os princípios da programação Alfabetizado, mas em C ++ eu rotineiramente me encontrar com std::pair, por tarefas gazillion comuns. Mas std::pair é, IMHO, um inimigo vil de programação alfabetizada ...

Meu ponto é quando eu voltar ao código que eu escrevi um dia ou dois atrás, e eu vejo manipulações de um std::pair (tipicamente como um iterador) Pergunto-me a mim mesmo " o que fez iter-> primeira e iter-> segunda média ??? ".

Eu estou supondo que os outros têm as mesmas dúvidas quando se olha para o seu código std::pair, então eu queria saber, alguém vir acima com algumas boas soluções para recuperar a alfabetização ao usar std::pair?

Foi útil?

Solução

Como sobre isto:

struct MyPair : public std::pair < int, std::string >
{
    const int& keyInt() { return first; }
    void keyInt( const int& keyInt ) { first = keyInt; }
    const std::string& valueString() { return second; }
    void valueString( const std::string& valueString ) { second = valueString; }
};

É um pouco detalhado, porém usando isso em seu código pode tornar as coisas um pouco mais fácil de ler, por exemplo:

std::vector < MyPair > listPairs;

std::vector < MyPair >::iterator iterPair( listPairs.begin() );
if ( iterPair->keyInt() == 123 )
    iterPair->valueString( "hello" );

Fora isso, eu não posso ver nenhuma bala de prata que vai tornar as coisas muito mais clara.

Outras dicas

std::pair é uma boa maneira de fazer um tipo de "local" e, essencialmente, anônimo com colunas essencialmente anônimos; se você estiver usando um determinado par sobre tão grande lexical espaço que você precisa para nomear o tipo e colunas, eu usaria um struct simples em vez.

typedef std::pair<bool, int> IsPresent_Value;
typedef std::pair<double, int> Price_Quantity;

... você começa o ponto.

Você pode criar dois pares de getters (const e não) que vai apenas retornar uma referência para o primeiro e segundo, mas será muito mais legível. Por exemplo:

string& GetField(pair& p) { return p.first; }
int& GetValue(pair& p) { return p.second; }

Será que você obter os membros de campo e valor de um determinado par sem ter que lembrar qual membro detém o.

Se você pretende usar muito isso, você também pode criar uma macro que irá gerar esses getters para você, dado os nomes e tipos: MAKE_PAIR_GETTERS (campo, corda, Valor, int) ou assim. Fazendo os getters simples, provavelmente vai permitir que o compilador para otimizar-los, então eles vão adicionar nenhuma sobrecarga em tempo de execução; e usando a macro vai fazer-lhe uma pressão para criar essas getters por qualquer uso que você faz de pares.

Você pode usar o aumento de tuplas, mas eles realmente não alterar a questão subjacente: Faça a sua realmente deseja acessar cada parte do par / tupla com um pequeno tipo integral, ou você quer mais código 'alfabetizados'. Consulte esta questão eu postei um tempo atrás.

No entanto, boost :: opcional é uma ferramenta útil que eu encontrei substitui muito poucos os casos em que pares / tuplas são apregoados como ther resposta.

Recentemente eu me encontrei usando boost::tuple como um substituto para std::pair. Você pode definir recenseadores para cada membro e por isso é óbvio que cada membro é:

typedef boost::tuple<int, int> KeyValueTuple;
enum {
  KEY
  , VALUE
};

void foo (KeyValueTuple & p) {
    p.get<KEY> () = 0;
    p.get<VALUE> () = 0;
}

void bar (int key, int value)
{
  foo (boost:tie (key, value));
}

BTW, comentários bem-vindo em se há um custo oculto para usar essa abordagem.

EDIT:. Nomes remover do escopo global

Apenas um rápido comentário sobre namespace global. Em geral, eu usaria:

struct KeyValueTraits
{
  typedef boost::tuple<int, int> Type;
  enum {
    KEY
    , VALUE
  };
};

void foo (KeyValueTuple::Type & p) {
    p.get<KeyValueTuple::KEY> () = 0;
    p.get<KeyValueTuple::VALUE> () = 0;
}

Ele faz olhar para ser o caso que boost::fusion não amarrar a identidade e valor mais juntos.

Como Alex mencionado, std::pair é muito conveniente, mas quando ele fica confuso criar uma estrutura e usá-lo da mesma forma, ter um olhar para o código std::pair, não é tão complexo.

Eu não gosto de std :: pair como usado em std :: map seja, entradas de mapa deveria ter tido membros chave e valor.
Eu mesmo usado boost :: MIC para evitar isso. No entanto, boost :: MIC também vem com um custo.

Além disso, retornando um std :: pair resultados em menos de código legível:

if (cntnr.insert(newEntry).second) { ... }

???

Eu também achei que std :: pair é comumente usado pelos programadores preguiçosos que precisavam de 2 valores mas não acho que por isso que esses valores quando necessário juntos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top