Почему std :: rel_ops :: operators не рекомендуется использовать в C++ 20?

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

В чем причина?

Вероятно, потому, что для C++ 20 принято трехстороннее сравнение.

Holt 13.04.2018 10:40
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
2
1 119
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

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

// Compiler generates 4 relational operators (you need to default the
// three-way comparison operator to get == and !=).
A to1, to2;
if (to1 > to2) { /* ... */ } // ok
if (to1 <= to2) { /* ... */ } // ok, single call to <=>

У трехстороннего сравнения по сравнению с 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.

Ничего не могу с собой поделать, но «оператор космического корабля» звучит намного круче, чем «трехстороннее сравнение»: P

463035818_is_not_a_number 13.04.2018 10:48

Насколько я понимаю, в большинстве случаев даже не потребуется внедрять <=>. Вместо этого можно будет писать std::strong_ordering operator<=>(const TotallyOrdered& that) const = default;

sv90 13.04.2018 11:29

@ sv90 Да, вы правы, я добавил в список плюсов маркер;)

Holt 13.04.2018 11:40

@ previouslyknownas_463035818: Думаю, слишком много [потенциальных] операторов оказались похожими на космические корабли ;-)

SamB 27.07.2019 16:47

В документе с умным названием «<=>! = ==» [1] нельзя получить «operator ==» от «operator <=>», если только оператор <=> не установлен по умолчанию. [1] Что можно перевести на Python как «__cmp__ is not __eq__»

Marcin Zdun 26.02.2020 14:29

@MarcinZdun Спасибо за точность, но я не знаю, что вы пытались сделать со ссылкой, но документ, который вы процитировали, недоступен.

Holt 26.02.2020 14:46

Ну, я не делал никаких ссылок на конкретный документ. «[1]» было ссылкой на ироничный «перевод» Python о том, как читать заголовок в той же заметке. Я просто не знал, что в комментариях нет символов новой строки, что слегка испортило шутку. Если вам интересно, фактический документ - P1185R1

Marcin Zdun 27.02.2020 15:09

@ L.F. Я потерялся. Я думал, что это именно то, что я сказал. Вы хотели перефразировать мой комментарий?

Marcin Zdun 30.03.2020 13:13

@MarcinZdun Извините, я пропустил часть, "если оператор <=> не установлен по умолчанию". Возможно, меня повредил вирус ...

L. F. 30.03.2020 13:15

C++ 20 предоставляет Трехстороннее сравнение, поэтому уникальные станут устаревшими.

What's the rationale behind?

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

This subsumes namespace std::rel_ops, so we propose also removing (or deprecating) std::rel_ops.

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

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)
  • Я упоминал, что это действительно работает?

Другие вопросы по теме