Me encuentro con un comportamiento extraño con el nuevo operador de nave espacial <=>
en C ++ 20. Estoy usando el compilador de Visual Studio 2019 con /std:c++latest
.
Este código se compila bien, como se esperaba:
#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;
}
Sin embargo, si cambio X a esto:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
Me sale el siguiente error del compilador:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
Intenté esto también en clang, y tengo un comportamiento similar.
Agradecería alguna explicación sobre por qué la implementación predeterminada se genera operator==
correctamente, pero la personalizada no.
fuente
Durante la estandarización de esta característica, se decidió que la igualdad y el orden deberían estar separados lógicamente. Como tal, los usos de las pruebas de igualdad (
==
y!=
) nunca invocaránoperator<=>
. Sin embargo, todavía se consideró útil poder predeterminarlos con una sola declaración. Por lo tanto, si establece un valor predeterminadooperator<=>
, se decidió que también tenía la intención de hacerlooperator==
(a menos que lo defina más tarde o lo haya definido antes).En cuanto a por qué se tomó esta decisión , el razonamiento básico es el siguiente. Considere
std::string
. El pedido de dos cadenas es lexicográfico; cada carácter tiene su valor entero comparado con cada carácter en la otra cadena. La primera desigualdad resulta en el resultado de ordenar.Sin embargo, la prueba de igualdad de cadenas tiene un cortocircuito. Si las dos cadenas no tienen la misma longitud, entonces no tiene sentido hacer una comparación entre caracteres; No son iguales. Entonces, si alguien está haciendo pruebas de igualdad, no querrá hacerlo de forma larga si puede hacer un corto circuito.
Resulta que muchos tipos que necesitan un pedido definido por el usuario también ofrecerán algún mecanismo de cortocircuito para las pruebas de igualdad. Para evitar que las personas solo implementen
operator<=>
y desechen el rendimiento potencial, obligamos a todos a hacer ambas cosas.fuente
Las otras respuestas explican muy bien por qué el lenguaje es así. Solo quería agregar que en caso de que no sea obvio, por supuesto, es posible que un usuario proporcione
operator<=>
un valor predeterminadooperator==
. Solo necesita escribir explícitamente el valor predeterminadooperator==
:fuente