O operador de igualdade não é definido para uma implementação de operador de nave espacial personalizada em C++ 20




c++20 spaceship-operator (2)

Estou tendo um comportamento estranho com o novo operador de nave espacial <=> no 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 uma explicação sobre por que a implementação padrão gera o operator== corretamente, mas o personalizado não.


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 um operator<=> fornecido pelo usuário operator<=> com um operator== padrão operator== . Você só precisa escrever explicitamente o operator== padrão operator== :

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
    bool operator==(const X& other) const = default;
};

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 chamarão o operator<=> . No entanto, ainda era considerado útil poder padronizar os dois com uma única declaração. Portanto, se você usar o operator<=> padrão operator<=> , foi decidido que você também pretende usar o operator== padrão operator== (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 cadeias 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 o operator<=> e joguem fora o desempenho potencial, forçamos efetivamente todos a fazer as duas coisas.





spaceship-operator