web-dev-qa-db-ja.com

なぜ“ b <a? 「a <b?」ではなく「a:b」 b:a”最大テンプレートを実装する?

C++テンプレート - 完全ガイド、第2版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”を使うことを説明します:

[StepanovNotes]に従ったmax()テンプレートは意図的に“ b <a?”を返すことに注意してください。 「a <b?」ではなく「a:b」 2つの値が等しいが等しくない場合でも、関数が正しく動作するようにする.

"even if the two values are equivalent but not equal."を理解するには? “a < b ? b : a”は私にとって同じ結果を持っているようです。

152
Nan Xiao

std::max(a, b)は、実際には両者が等しい場合にaを返すように指定されています。

abを与えた便利なプロパティを壊してしまうので、これは Stepanov その他による間違いと見なされます。{min(a, b), max(a, b)}でそれらをソートすることができます。そのためには、引数が同等の場合はmax(a, b)bを返すようにします。

151
T.C.

この答えは、与えられたコードがC++標準の観点からは間違っている理由を説明していますが、文脈から外れています。

文脈上の説明は @T.C.の答え を参照。


規格は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)true[alg.sorting#7] であることを意味します。

特に、abが同等の場合、a < bb < aの両方がfalseであるため、:の右側の値が条件演算子に返されるため、aは右側に配置する必要があります。

a < b ? b : a

...正解のようです。これは libstdc ++ および libc ++ で使用されているバージョンです。

だからあなたの引用の中の情報は現在の規格によれば間違っているように見えますが、それが定義されている文脈は異なるかもしれません。

63
Holt

重要な点は、それらが同等の場合にどちらを返すべきかということです。この場合、 std::maxa(つまり最初の引数)を返す必要があります。

それらが等価であれば、aを返します。

そのためa < b ? b : aを使うべきです。一方、b < a ? a : b;bを誤って返します。

(@Holtが言ったように、引用は反対に見えます。)

「2つの値は同等だが等しくない」とは、比較時に同じ値を持つことを意味しますが、他の側面では異なるオブジェクトに移行します。

例えば.

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's guaranteed that an X which cantains {0, 1} is returned
21
songyuanyao