Почему 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
) - Я упоминал, что это действительно работает?
Ответ 3
С++ 20 prvides. Трехстороннее сравнение, таким образом, уникальные станут устаревшими.