Почему в C++20 убрали оператор != у std::bitset?
Почему в C++20 убрали оператор != у std::bitset?
Ответы (2 шт):
В C++20 устаревшими стали все операторы сравнения кроме == и <=>, потому что последний включает их в себя. Т.е. код по-прежнему будет работать, но не будет вызываться отдельный оператор != для этого.
Подробности в этом вопросе https://stackoverflow.com/q/49812708.
Потому что начиная с версии стандарта 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) приведет к ошибке.
Рассмотрим сравение из примера выше: a1 != a2. На этапе компиляции выполняется поиск имен, и здесь возможно несколько вариантов развития событий:
- Вы явно определили
operator!=, name lookup разрешен в пользу этого оператора, он и будет вызван. - Явное определение
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 != AnnotationAnnotation != 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.