Почему std :: rel_ops :: operator устаревают в С++ 20?

Согласно cppreference.com, std::rel_ops::operator!=,>,<=,>= Будет устаревшим в С++ 20.

Какое обоснование?

Ответы

Ответ 1

В С++ 20 вы получаете трехстороннее сравнение (оператор <=>), который автоматически "генерирует" сравнения по умолчанию, если они предоставляются:

struct A {
   // You only need to implement a single operator.
   std::strong_ordering operator<=>(const A&) const;
};

// Compiler generates all 6 relational operators
A to1, to2;
if (to1 == to2) { /* ... */ } // ok
if (to1 <= to2) { /* ... */ } // ok, single call to <=>

Существует несколько преимуществ трехстороннего сравнения по std::rel_ops, что, вероятно, является std::rel_ops, что оператор std::rel_ops устарел. Наверху:

  • Он более универсален, поскольку в зависимости от типа возвращаемого operator<=> (std::strong_ordering, std::weak_ordering ,...) генерируются только соответствующие операторы. Дополнительную информацию см. В заголовке <compare>.

  • Вы не приносите кучу шаблонных перегрузок операторов, using namespace std::rel_ops.

  • Вы можете попросить компилятор генерировать трехсторонний оператор для вас, выполнив его по auto operator<=>(A const&) = default (auto operator<=>(A const&) = default). Это будет в основном генерировать лексикографическое сравнение базовых классов и нестатических членов данных, плюс его будет выводить правильный тип упорядочения, если тип возврата auto.

Ответ 2

Какое обоснование?

rel_ops не поддерживалась поддержкой библиотеки для оператора космического корабля (сравнения). В документе не указаны какие-либо мотивации, но она появляется в документе космического корабля:

Это подразумевает пространство имен std::rel_ops, поэтому мы предлагаем также удаление (или устаревание) std::rel_ops.

Есть четыре причины, упомянутые в документе (включая правильность и производительность). Но один большой, который не упоминается ни в одной из статей, заключается в том, что std::rel_ops просто... не работает. Правило большого пальца состоит в том, что операторы найдены с использованием ADL. rel_ops не дает вам ADL-findable-операторов, он просто объявляет неограниченные шаблоны функций, например:

namespace std {
    namespace rel_ops {
        template< class T >
        bool operator!=( const T& lhs, const T& rhs ) 
        {
            return !(lhs == rhs);
        }
    }    
}

Таким образом, используя алгоритмы вроде:

struct X { ... };
bool operator<(X const&, X const&) { ... };
std::sort(values.begin(), values.end(), std::greater<>{});

Просто не работает, если вы не убедитесь:

#include <utility>
using namespace std::rel_ops;

Достаточно последовательно повсюду, так как в первую очередь вы должны убедиться, что эти операторы видны в точке определения каждого шаблона функции, который вы могли бы вызвать.

Таким образом, operator<=> просто строго превосходит:

  • Это действительно работает.
  • Вам нужно только написать одну функцию (<=>) вместо двух (== и <)
  • Обычно вам приходится писать нулевые функции (= default)
  • Я упоминал, что это действительно работает?