Мотивация определения концепции отношения в C++20

Как онлайн-черновик C++, так и cppreference определяет стандартную Relation концепцию следующим образом:

template <class R, class T, class U>
concept Relation =
  std::Predicate<R, T, T> && std::Predicate<R, U, U> &&
  std::Predicate<R, T, U> && std::Predicate<R, U, T>;

Это определение меня удивляет, так как я ожидал увидеть что-то вроде

template <class R, class T, class U>
concept Relation = std::Predicate<R, T, U>;

или, вероятно,

template <class R, class T, class U>
concept Relation = std::Predicate<R, T, U> && std::Predicate<R, U, T>;

или даже

template <class R, class T, class U>
concept Relation = std::Predicate<R, T, U> || std::Predicate<R, U, T>;

Насколько я понимаю, отношение между типами T и U является бинарным предикатом для пар (T, U). Таким образом, нет смысла оценивать отношение двух объектов типа T или двух объектов типа U. Однако данное определение требует, чтобы отношение можно было вызывать с аргументами (T,T) и (U,U).

Мой вопрос: какова мотивация этого (кажущегося неверным) определения концепции Relation?

Объяснение, данное на cppreference, гласит, что

Концепция Relation указывает, что R определяет бинарное отношение над набором выражений, тип и категория значений которых кодируются либо T, либо U.

(выделено мной)

Мне это кажется странным: почему общая концепция Relation определяется двумя вспомогательными аргументами двух типов, используемыми в любой комбинации?

Одна возможность может заключаться в том, что эта концепция используется для сравнения указателей и nullptr_t, а также для сравнения итераторов и итераторов-стражей. Если это так, то почему это понятие называется Relation, а не чем-то более конкретным, например, InterComparable? Это просто неправильное название?


person lisyarus    schedule 23.05.2019    source источник
comment
между прочим, объяснение cppref довольно хорошо соответствует определению R определяет бинарное отношение над набором выражений, тип и категория значения которых закодированы либо T, либо U., хотя я согласен, что это странно способ определения бинарного отношения   -  person 463035818_is_not_a_number    schedule 23.05.2019
comment
@formerlyknownas_463035818 Да, я видел эту фразу, спасибо. Однако это не объясняет, почему существует два типа, каждый из которых представляет возможный тип аргумента. Почему не один тип? Почему бы, скажем, не семнадцать типов? Набор возможных типов аргументов, по-видимому, никак не связан с количеством аргументов. Я обновлю вопрос, спасибо.   -  person lisyarus    schedule 23.05.2019
comment
Я бы сказал, что это просто неправильное название. Predicate уже является отношением, которое вы ожидаете. Relation позволяет расширить набор типов, так что Relation<R, A, B> может быть прочитано как Predicate<R, A U B, A U B> (с U в качестве объединения для набора).   -  person Jarod42    schedule 23.05.2019


Ответы (1)


Это неправильное название. Насколько я могу судить, он существует для обеспечения синтаксических требований для таких вещей, как StrictWeakOrder без семантических требований.

Например. рассмотреть также

template <class R, class T, class U>
concept Equivalence = std::Relation<R, T, U>;

//A relation r is an equivalence if
// - it is reflexive: for all x, r(x, x) is true;
// - it is symmetric: for all a and b, if r(a, b) is true then r(b, a) is true;
// - it is transitive: for all a, b and c, if r(a, b) and r(b, c) are both true then r(a, c) is true;
person Caleth    schedule 23.05.2019
comment
Relation используется не только в качестве строительного блока для StrictWeakOrder. Если бы это было так, в этом не было бы необходимости. - person Barry; 23.05.2019