Estou tendo um comportamento estranho com o novo operador de nave espacial <=>
em C ++ 20. Estou usando o compilador do Visual Studio 2019 com /std:c++latest
.
Esse código compila bem, conforme o esperado:
#include <compare>
struct X
{
int Dummy = 0;
auto operator<=>(const X&) const = default; // Default implementation
};
int main()
{
X a, b;
a == b; // OK!
return 0;
}
No entanto, se eu alterar X para isso:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
Eu recebo o seguinte erro do compilador:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
Eu tentei isso no clang também, e recebo um comportamento semelhante.
Gostaria de receber algumas explicações sobre por que a implementação padrão gera operator==
corretamente, mas a personalizada não.
fonte
Durante a padronização desse recurso, foi decidido que a igualdade e a ordem deveriam ser logicamente separadas. Como tal, os usos do teste de igualdade (
==
e!=
) nunca serão invocadosoperator<=>
. No entanto, ainda era considerado útil poder padronizar os dois com uma única declaração. Portanto, se você usar o padrãooperator<=>
, foi decidido que você também deveria usar o padrãooperator==
(a menos que você o defina mais tarde ou o defina anteriormente).Quanto ao motivo pelo qual essa decisão foi tomada , o raciocínio básico é o seguinte. Considere
std::string
. A ordenação de duas strings é lexicográfica; cada caractere tem seu valor inteiro comparado a cada caractere na outra sequência. A primeira desigualdade resulta no resultado do pedido.No entanto, o teste de igualdade de strings tem um curto-circuito. Se as duas seqüências não tiverem o mesmo comprimento, não faz sentido fazer uma comparação entre caracteres; eles não são iguais. Portanto, se alguém estiver testando a igualdade, você não deseja fazê-lo de forma longa, se conseguir um curto-circuito.
Acontece que muitos tipos que precisam de uma ordem definida pelo usuário também oferecerão algum mecanismo de curto-circuito para teste de igualdade. Para impedir que as pessoas implementem apenas
operator<=>
e joguem fora o desempenho potencial, forçamos efetivamente todos a fazer as duas coisas.fonte
As outras respostas explicam muito bem por que a linguagem é assim. Eu só queria acrescentar que, caso não seja óbvio, é claro que é possível ter
operator<=>
um padrão fornecido pelo usuáriooperator==
. Você só precisa escrever explicitamente o padrãooperator==
:fonte