Я столкнулся со странным поведением с новым оператором космического корабля <=>
в C ++ 20. Я использую компилятор Visual Studio 2019 с /std:c++latest
.
Этот код компилируется нормально, как и ожидалось:
#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;
}
Однако, если я изменю X на это:
struct X
{
int Dummy = 0;
auto operator<=>(const X& other) const
{
return Dummy <=> other.Dummy;
}
};
Я получаю следующую ошибку компилятора:
error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator
Я попробовал это и на Clang, и у меня похожее поведение.
Я был бы признателен за объяснение того, почему реализация по умолчанию генерируется operator==
правильно, а пользовательская - нет.
источник
Во время стандартизации этой функции было решено, что равенство и порядок должны быть логически разделены. Таким образом, использование проверки на равенство (
==
и!=
) никогда не вызоветoperator<=>
. Тем не менее, все еще считалось полезным иметь возможность использовать их по умолчанию в одном объявлении. Поэтому, если вы по умолчаниюoperator<=>
, было решено, что вы также имели в виду по умолчаниюoperator==
(если вы не определили его позже или определили его ранее).Относительно того, почему было принято это решение , основные рассуждения таковы. Посмотрим
std::string
. Порядок двух строк лексикографический; каждый символ имеет свое целочисленное значение по сравнению с каждым символом в другой строке. Первое неравенство приводит к результату упорядочения.Однако проверка равенства строк имеет короткое замыкание. Если две строки не имеют одинаковую длину, тогда нет смысла делать посимвольное сравнение вообще; они не равны. Поэтому, если кто-то проводит тестирование на равенство, вы не хотите делать его длинным, если можете его замкнуть.
Оказывается, что многие типы, которым требуется пользовательский порядок, также предлагают некоторый механизм короткого замыкания для проверки на равенство. Чтобы люди не реализовывали
operator<=>
и не отбрасывали потенциальную производительность, мы эффективно заставляем всех делать то и другое.источник
Другие ответы очень хорошо объясняют, почему язык такой. Я просто хотел добавить, что в случае, если это не очевидно, конечно, возможно предоставить пользователю
operator<=>
дефолтoperator==
. Вам просто нужно явно написать значение по умолчаниюoperator==
:источник