Зачем использовать "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