Зачем использовать "b <a? A: b" вместо "a <b? B: a" для реализации максимального шаблона?

Шаблоны C++ - полное руководство, второе издание представляет шаблон max:

template<typename T>
T max (T a, T b)
{
  // if b < a then yield a else yield b
  return  b < a ? a : b;
}

И это объясняет использование "b < a? a: b" вместо "a < b? b: a":

Обратите внимание, что шаблон max() в соответствии с [StepanovNotes] намеренно возвращает "b <a? A: b" вместо "a <b? B: a", чтобы гарантировать, что функция ведет себя корректно, даже если эти два значения эквивалентны, но не равны.

Как понимать " even if the two values are equivalent but not equal. "? "a < b? b: a" похоже, имеет для меня тот же результат.

Ответ 1

std::max(a, b) действительно задан для возврата a когда эти два эквивалентны.

Это считало ошибку Степановым и другими, потому что оно ломает полезное свойство, которое дает a и b, вы всегда можете сортировать их с помощью {min(a, b), max(a, b)}; для этого вам нужно, чтобы max(a, b) возвращал b когда аргументы эквивалентны.

Ответ 2

Этот ответ объясняет, почему данный код не соответствует стандартной точке зрения C++, но он не соответствует контексту.

См. Ответ @TC для контекстного объяснения.


Стандарт определяет std::max(a, b) следующим образом [alg.min.max] (акцент мой):

template<class T> constexpr const T& max(const T& a, const T& b);

Требуется: Тип T является LessThanComparable (Таблица 18).

Возвраты: большее значение.

Примечания. Возвращает первый аргумент, когда аргументы эквивалентны.

Эквивалент здесь означает, что !(a < b) && !(b < a) A !(a < b) && !(b < a) true [alg.sorting # 7].

В частности, если a и b эквивалентны, оба a < b и b < a являются false, поэтому значение справа от : будет возвращено в условном операторе, поэтому a должно быть справа, поэтому:

a < b ? b : a

... кажется правильным ответом. Это версия, используемая libstd C++ и lib C++.

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

Ответ 3

Дело в том, что нужно возвращать, когда они эквивалентны; std::max должен вернуть (т.е. первый аргумент) для этого случая. a

Если они эквивалентны, возвращает a.

Итак, a < b? b: a a < b? b: a следует использовать; с другой стороны, b < a? a: b; b < a? a: b; неверно вернет b.

(Как сказал @Хольт, цитата кажется противоположной.)

"эти два значения эквивалентны, но не равны" означает, что они имеют одинаковое значение при сравнении, но они могут быть разными объектами в некоторых других аспектах.

например

struct X { int a; int b; };
bool operator< (X lhs, X rhs) { return lhs.a < rhs.a; }
X x1 {0, 1};
X x2 {0, 2};
auto x3 = std::max(x1, x2); // it guaranteed that an X which cantains {0, 1} is returned