Por que o operador! = Foi removido no C ++ 20 para muitos tipos de biblioteca padrão?

44

De acordo com a cppreference , std::type_info::operator!=é removido com o C ++ 20, no entanto, std::type_info::operator==aparentemente permanece.

Qual é o raciocínio por trás? Eu poderia concordar em comparar a desigualdade sem sentido, mas comparar a igualdade seria igualmente sem sentido, não é?

Da mesma forma, operator!=de muitos outros tipos de biblioteca padrão, incluindo contêineres como std::unordered_map::operator!=e std::unordered_set::operator!=serão removidos no C ++ 20 de acordo com a cppreference.

Ter que escrever if(!(id1 == id2))não torna nenhum código mais claro se comparado ao if(id1 != id2)contrário ...

Aconcágua
fonte

Respostas:

62

Em C ++ 20, a maneira como os operadores relacionais trabalham foi alterada, principalmente com a introdução do <=>operador de espaçonave . Em particular, se você fornecer apenas operator==, a != bserá reescrito para !(a == b).

De [over.match.oper] /3.4 :

O conjunto de candidatos reescritos é determinado da seguinte maneira:

  • Para os operadores relacionais ([expr.rel]), os candidatos reescritos incluem todos os candidatos não reescritos para a expressão x <=> y.
  • Para os operadores relacionais ([expr.rel]) e de comparação de três vias ([expr.spaceship]), os candidatos reescritos também incluem um candidato sintetizado, com a ordem dos dois parâmetros revertidos, para cada candidato não reescrito para o expressão y <=> x.
  • Para o operador! = ([Expr.eq]), os candidatos reescritos incluem todos os candidatos não reescritos para a expressão x == y.
  • Para os operadores de igualdade, os candidatos reescritos também incluem um candidato sintetizado, com a ordem dos dois parâmetros revertidos, para cada candidato não reescrito para a expressão y == x.
  • Para todos os outros operadores, o conjunto de candidatos reescritos está vazio.

E [over.match.oper] / 9 :

Se um operador reescrito == candidato for selecionado por resolução de sobrecarga para um operador @, seu tipo de retorno será cv bool e x @ y será interpretado como:

  • se @ for! = e o candidato selecionado for um candidato sintetizado com ordem inversa de parâmetros,! (y == x),
  • caso contrário, se @ for! =,! (x == y) ,
  • caso contrário (quando @ for ==), y == x,

em cada caso, usando o operador reescrito selecionado == candidato.

Como tal, uma sobrecarga explícita para operator!=não é mais necessária. A remoção do operador não mudou a semântica da comparação.

Todos os contêineres foram operator!=removidos, até onde eu sei (verifique, por exemplo, a sinopse do vetor ). As únicas exceções são os adaptadores de contêiner std::queuee std::stack: meu palpite é que é para preservar a compatibilidade com versões anteriores quando usado com contêineres de terceiros, caso os operadores de igualdade não sejam simétricos.

N. Shead
fonte
7
O p1614 também pode ser interessante, pois acredito que foi a proposta que removeu as sobrecargas.
N. Shead
39

Não precisamos mais de uma biblioteca fornecida operator!=. O fornecimento operator==permite que o compilador faça algum malabarismo e avalie a != bem termos de a == b, tudo por conta própria.

[over.match.oper]

3 Para um operador unário @ com um operando de um tipo cuja versão não qualificada de cv é T1, e para um operador binário @ com um operando esquerdo de um tipo cuja versão não qualificada de cv é T1 e um operando direito de um tipo cuja cv- versão não qualificada é T2, quatro conjuntos de funções candidatas, candidatos a membros designados, candidatos a não membros, candidatos internos e candidatos reescritos são construídos da seguinte maneira:

3.4.3 Para o operador! = ([Expr.eq]), os candidatos reescritos incluem todos os candidatos não reescritos para a expressão x == y.

std::type_infoe muitos outros tipos de bibliotecas foram operator!=removidos como parte do P1614 - The Mothership Landed .

Contador de Histórias - Monica Sem Calúnia
fonte