Мотивация определения понятия «отношение» в C ++ 20 - PullRequest
4 голосов
/ 23 мая 2019

Обе онлайн-версия 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? Это просто неправильно?

1 Ответ

4 голосов
/ 23 мая 2019

Это неправильно.Насколько я могу судить, он существует для обеспечения синтаксических требований для таких вещей, как 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;
...