Ich habe ein seltsames Verhalten mit dem neuen Raumschiffoperator <=>
in C ++ 20. Ich verwende den Visual Studio 2019-Compiler mit /std:c++latest
.
Dieser Code wird wie erwartet gut kompiliert:
#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;
}
Wenn ich jedoch X in Folgendes ändere :
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
Ich erhalte den folgenden Compilerfehler:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
Ich habe das auch bei Clang versucht und bekomme ein ähnliches Verhalten.
Ich würde mich über eine Erklärung freuen, warum die Standardimplementierung operator==
korrekt generiert wird, die benutzerdefinierte jedoch nicht.
quelle
Während der Standardisierung dieser Funktion wurde entschieden, dass Gleichheit und Reihenfolge logisch getrennt werden sollten. Daher wird die Verwendung von Gleichheitstests (
==
und!=
) niemals aufgerufenoperator<=>
. Es wurde jedoch immer noch als nützlich angesehen, beide mit einer einzigen Deklaration als Standard festlegen zu können. Wenn Sie also einen Standardwert festlegenoperator<=>
, wurde entschieden, dass Sie auch einen Standardwertoperator==
festlegen möchten (es sei denn, Sie definieren ihn später oder haben ihn früher definiert).Die Gründe für diese Entscheidung lauten wie folgt: Überlegen Sie
std::string
. Die Reihenfolge von zwei Zeichenfolgen ist lexikografisch. Jedes Zeichen hat einen ganzzahligen Wert, der mit jedem Zeichen in der anderen Zeichenfolge verglichen wird. Die erste Ungleichung führt zum Ergebnis der Bestellung.Die Gleichheitsprüfung von Strings weist jedoch einen Kurzschluss auf. Wenn die beiden Zeichenfolgen nicht gleich lang sind, macht es keinen Sinn, einen zeichenweisen Vergleich durchzuführen. Sie sind nicht gleich. Wenn also jemand Gleichheitstests durchführt, möchten Sie dies nicht in Langform tun, wenn Sie es kurzschließen können.
Es stellt sich heraus, dass viele Typen, die eine benutzerdefinierte Reihenfolge benötigen, auch einen Kurzschlussmechanismus für Gleichheitstests bieten. Um zu verhindern, dass Menschen nur implementieren
operator<=>
und potenzielle Leistung wegwerfen, zwingen wir alle effektiv dazu, beides zu tun.quelle
Die anderen Antworten erklären wirklich gut, warum die Sprache so ist. Ich wollte nur hinzufügen, dass es für den Fall, dass es nicht offensichtlich ist, natürlich möglich ist, dass ein Benutzer
operator<=>
eine Standardeinstellung erhältoperator==
. Sie müssen nur explizit die Standardeinstellung schreibenoperator==
:quelle