Оператор равенства не определен для пользовательской реализации оператора космического корабля в C ++ 20

Я столкнулся со странным поведением с новым оператором космического корабля <=> в 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== правильно, а пользовательская - нет.

39
задан Miljen Mikic 14 November 2019 в 12:57
поделиться

3 ответа

Это дизайном.

[class.compare.default] (шахта акцента)

3 , Если определение класса явно не объявляет == функция оператора, но объявляет , принял значение по умолчанию трехсторонний оператор сравнения функция, ==, функция оператора объявляется неявно с тем же доступом как трехсторонняя функция оператора сравнения. Неявно объявленный == оператор для класса X является встроенным участником и определяется, как принял значение по умолчанию в определении X.

, Только принявший значение по умолчанию <=> позволит синтезируемому == существовать. Объяснение является классами как std::vector. Это, очевидно, не может использовать принявший значение по умолчанию <=>. И это именно так происходит, что включение <=> для ==, когда сравнение векторов не является самым эффективным способом сравнить их. <=> должен дать точное упорядочивание, тогда как == может взять на поруки рано путем сравнения размеров сначала.

, Если класс делает что-то специальное в своем трехстороннем сравнении, более, чем вероятно, что это должно будет сделать что-то специальное в ==. Таким образом вместо того, чтобы генерировать неразумное значение по умолчанию, язык оставляет его до программиста.

45
ответ дан 27 November 2019 в 02:16
поделиться

Другие ответы объясняют действительно хорошо, почему язык похож на это. Я просто хотел добавить, что в случае, если это не очевидно, конечно, возможно иметь обеспеченный пользователями operator<=> с принявшим значение по умолчанию operator==. Просто необходимо явно записать принявший значение по умолчанию operator==:

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
    bool operator==(const X& other) const = default;
};
14
ответ дан 27 November 2019 в 02:16
поделиться

Во время стандартизации этой функции было решено, чтобы равенство и упорядочивание были логически разделены. По сути, использование тестирования равенства (== и !=) будет никогда , вызывают operator<=>. Однако это, как все еще рассматривалось, как полезное смогло принять значение по умолчанию они оба с единственным объявлением. Таким образом, если Вы принимаете значение по умолчанию operator<=>, было решено также значить для значения по умолчанию operator== (если Вы не определяете его позже или определили его ранее).

относительно , почему это решение было принято , основное обоснование идет как это. Рассмотрите std::string. Упорядочивание двух строк является лексикографическим; каждому символу сравнили его целочисленное значение с каждым символом в другой строке. Первое неравенство приводит к результату упорядочивания.

Однако тестирование равенства строк имеет короткое замыкание. Если две строки не имеют равной длины, то нет никакого смысла в выполнении символьно-мудрого сравнения вообще; они не равны. Таким образом, если кто-то делает тестирование равенства, Вы не хотите делать это подробная форма, если можно закоротить его.

оказывается, что много типов, которым нужно пользовательское упорядочивание, также предложат некоторый механизм короткого замыкания для тестирования равенства. Чтобы препятствовать тому, чтобы люди реализовали только operator<=> и выбросили потенциальную производительность, мы эффективно вынуждаем всех сделать обоих.

38
ответ дан 27 November 2019 в 02:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: