L'operatore di uguaglianza non viene definito per un'implementazione personalizzata dell'operatore di astronave in C++ 20
c++20 spaceship-operator (2)
Durante la standardizzazione di questa funzionalità, è stato deciso che l'uguaglianza e l'ordinamento dovrebbero essere logicamente separati.
Pertanto, l'uso del test di uguaglianza (
==
e
!=
)
Non
invocherà
mai l'
operator<=>
.
Tuttavia, è stato ancora considerato utile essere in grado di predefinire entrambi con una singola dichiarazione.
Quindi, se l'
operator<=>
predefinito
operator<=>
, è stato deciso che intendevi anche l'
operator==
predefinito
operator==
(a meno che non lo definissi in seguito o lo avessi definito in precedenza).
Per quanto riguarda il
motivo
per
cui questa decisione è stata presa
, il ragionamento di base va così.
Considera
std::string
.
L'ordinamento di due stringhe è lessicografico;
ogni carattere ha il suo valore intero rispetto a ciascun carattere nell'altra stringa.
La prima disuguaglianza si traduce nel risultato dell'ordine.
Tuttavia, il test di uguaglianza delle stringhe ha un corto circuito. Se le due stringhe non hanno la stessa lunghezza, non ha senso fare un confronto saggio; non sono uguali. Quindi, se qualcuno sta facendo dei test sull'uguaglianza, non vorrai farlo a lungo se riesci a cortocircuitare.
Si scopre che molti tipi che richiedono un ordinamento definito dall'utente offriranno anche alcuni meccanismi di cortocircuito per i test di uguaglianza.
Per impedire alle persone di implementare solo l'
operator<=>
e di gettare via le potenziali prestazioni, forziamo efficacemente tutti a fare entrambe le cose.
Sto riscontrando uno strano comportamento con il nuovo operatore dell'astronave
<=>
in C ++ 20.
Sto usando Visual Studio 2019 compilatore con
/std:c++latest
.
Questo codice viene compilato correttamente, come previsto:
#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;
}
Tuttavia, se cambio X in questo:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
Ottengo il seguente errore del compilatore:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
Ho provato anche questo su clang e ho un comportamento simile.
Gradirei qualche spiegazione sul perché l'implementazione predefinita genera correttamente
operator==
, ma quella personalizzata no.
Le altre risposte spiegano molto bene perché la lingua è così.
Volevo solo aggiungere che nel caso in cui non fosse ovvio, è ovviamente possibile avere un
operator<=>
fornito dall'utente
operator<=>
con un
operator==
predefinito
operator==
.
Devi solo scrivere esplicitamente l'
operator==
predefinito
operator==
:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
bool operator==(const X& other) const = default;
};