Почему оператор! = Удален в C ++ 20 для многих стандартных типов библиотек?

44

Согласно cppreference , std::type_info::operator!=удаляется с C ++ 20, однако, по- std::type_info::operator==видимому, остается.

В чем причина? Я мог бы согласиться с тем, что сравнивать неравенство бессмысленно, но тогда сравнивать равенство было бы так же бессмысленно, не так ли?

Точно так же operator!=из многих других стандартных типов библиотек, включая контейнеры, такие как std::unordered_map::operator!=и std::unordered_set::operator!=будут удалены в C ++ 20 в соответствии с cppreference.

Необходимость писать if(!(id1 == id2))не делает код более понятным по сравнению с if(id1 != id2)противоположным ...

Аконкагуа
источник

Ответы:

62

В C ++ 20 был изменен способ работы реляционных операторов, особенно с введением <=>оператора космического корабля . В частности, если вы только предоставляете operator==, то a != bпереписывается на !(a == b).

Из [over.match.oper] /3.4 :

Переписанный набор кандидатов определяется следующим образом:

  • Для реляционных ([expr.rel]) операторов переписанные кандидаты включают все не переписанные кандидаты в выражение x <=> y.
  • Для операторов реляционного ([expr.rel]) и трехстороннего сравнения ([expr.spaceship]) переписанные кандидаты также включают в себя синтезированный кандидат с обратным порядком двух параметров для каждого не переписанного кандидата для выражение у <=> х.
  • Для оператора! = ([Expr.eq]) переписанные кандидаты включают в себя все не переписанные кандидаты для выражения x == y.
  • Для операторов равенства переписанные кандидаты также включают в себя синтезированный кандидат с обратным порядком двух параметров для каждого не переписанного кандидата для выражения y == x.
  • Для всех остальных операторов переписанный набор кандидатов пуст.

И [over.match.oper] / 9 :

Если переписанный оператор == кандидат выбран разрешением перегрузки для оператора @, его тип возвращаемого значения должен быть cv bool, а x @ y интерпретируется как:

  • если @ =! = и выбранный кандидат является синтезированным кандидатом с обратным порядком параметров,! (y == x),
  • в противном случае, если @ =! =,! (x == y) ,
  • в противном случае (когда @ ==), y == x,

в каждом случае используется выбранный переписанный оператор == кандидат.

Таким образом, явная перегрузка для operator!=более не требуется. Удаление оператора не изменило семантику сравнения.

operator!=Насколько я могу судить, все контейнеры были удалены (см., Например, векторный синопсис ). Единственными исключениями являются адаптеры контейнеров std::queueи std::stack: я предполагаю, что он должен сохранять обратную совместимость при использовании со сторонними контейнерами, если операторы равенства не симметричны.

Н. Шеад
источник
7
p1614 также может быть интересен, так как я считаю, что это предложение убрало перегрузки.
Н. Шед
39

Нам больше не нужна библиотека operator!=. Предоставление operator==позволяет компилятору делать некоторые манипуляции и оценивать a != bс точки зрения a == b, все самостоятельно.

[Over.match.oper]

3 Для унарного оператора @ с операндом типа, cv-неквалифицированная версия которого равна T1, и для бинарного оператора @ с левым операндом типа, cv-неквалифицированная версия которого равна T1, и правым операндом типа, cv- безусловной версией является T2, четыре набора функций-кандидатов, назначенные кандидаты в члены, кандидаты, не являющиеся членами, встроенные кандидаты и переписанные кандидаты, сконструированы следующим образом:

3.4.3 Для оператора! = ([Expr.eq]) переписанные кандидаты включают все не переписанные кандидаты для выражения x == y.

std::type_infoи многие другие типы библиотек были operator!=удалены как часть P1614 - Материнство приземлилось .

Рассказчик - Unslander Monica
источник