Почему в C++20 убрали оператор != у std::bitset?

Почему в C++20 убрали оператор != у std::bitset?


Ответы (2 шт):

Автор решения: user393524

В C++20 устаревшими стали все операторы сравнения кроме == и <=>, потому что последний включает их в себя. Т.е. код по-прежнему будет работать, но не будет вызываться отдельный оператор != для этого.

Подробности в этом вопросе https://stackoverflow.com/q/49812708.

→ Ссылка
Автор решения: isnullxbh

Потому что начиная с версии стандарта C++20 в нем (явном определении) просто больше нет необходимости. Разумеется, это не значит, что его нельзя использовать.

Теперь достаточно определить operator== и выражение, в котором используется operator!= будет преобразовано в !operator==(...).


Приведу пример:

// -std=c++2a

#include <iostream>
#include <string>

class Annotation
{
public:
    Annotation() = default;
    explicit Annotation(std::string data) : m_data(std::move(data)) {}

public:
    friend auto operator==(const Annotation& lhs, const Annotation& rhs) -> bool
    {
        return lhs.m_data == rhs.m_data;
    }

protected:
    std::string m_data {};
};

auto main() -> int
{
    Annotation a1 { "abc" };
    Annotation a2 { "xyz" };

    std::cout << std::boolalpha << (a1 != a2) << std::endl;
}

Как видите, явное определение для operator!= в данном примере отсутствует, тем не менее этот код является корректным. Попытка скомпилировать этот код с -std=c++17 (/std:c++17) приведет к ошибке.

Wandbox Live Example


Рассмотрим сравение из примера выше: a1 != a2. На этапе компиляции выполняется поиск имен, и здесь возможно несколько вариантов развития событий:

  1. Вы явно определили operator!=, name lookup разрешен в пользу этого оператора, он и будет вызван.
  2. Явное определение operator!= отсутствует, при этом оператор operator== определен, выражение a1 != a2 будет преобразовано к виду !operator==(a1, a2).

Второй пункт требует уточнения, давайте посмотрим еще один пример:

class ExtendedAnnotation : public Annotation
{
public:
    ExtendedAnnotation() = default;

public:
    friend auto operator==(const ExtendedAnnotation& lhs, const Annotation& rhs) -> bool
    {
        return lhs.m_data.starts_with(rhs.data());
    }
};

Непосредственно сравнение:

auto main() -> int
{
    Annotation         a1;
    ExtendedAnnotation a2;

    std::cout << std::boolalpha << (a1 != a2) << std::endl;
    std::cout << std::boolalpha << (a2 != a1) << std::endl;
}

Как Вы можете заметить, я определил только operator==(const ExtendedAnnotation&, const Annotation&), однако работают оба варианта:

  • ExtendedAnnotation != Annotation
  • Annotation != ExtendedAnnotation

Т.е., при name lookup так же проверяются кандидаты с обратным порядком аргументов.


Более детальное описание Вы можете найти в over.match.oper.

For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == y.

If a rewritten operator== candidate is selected by overload resolution for and operator @, its return type shall be cv bool, and x @ y is interpreted as:

  • (9.1) if @ is != and the selected candidate is a synthesized candidate with reversed order of parameters, !(y == x),
  • (9.2) otherwise, if @ is !=, !(x == y),
  • (9.3) otherwise (when @ is ==), y == x,
    in each case using the selected rewritten operator== candidate.
→ Ссылка