ある意味で他の2つは暗黙的ですが、より正確には、比較ソートは実際には3値のコンパレータを必要とせず、C ++のソートは、最小化するために1つを使用しない方法で実装されます。コンパレータに必要な動作。
std :: sortが次のようなものを定義して排他的に使用するのは間違っているでしょう:
template <typename T, typename Cmp>
int get_tri_value(const T &a, const T &b, Cmp lessthan) {
if (lessthan(a,b)) return -1;
if (lessthan(b,a)) return 1;
return 0;
}
...への呼び出しの数に関して非効率的なアルゴリズムになってしまうためですlessthan
。アルゴリズムが1リターンと0リターンの違いで何の役にも立たない場合は、比較を無駄にしています。
C ++は、「厳密な弱順序」を指します。<
が厳密な弱順序である場合、および、は必ずしもそれに続く!(a < b) && !(b < a)
とは限りません。それらは順序付けの「同じ場所」にあり、同値関係です。したがって、オブジェクトの順序等価クラスに必要なコンパレータは、全順序を提供しません。a == b
!(a < b) && !(b < a)
sort
それが作る唯一の違いは、あなたがいつ言うかです!(a < b)
。厳密な全順序については、b <= a
「以下」と読み替えてください。b <= a
厳密な弱順序の場合、これを意味するように定義しb < a || b == a
て、これを真にすることはできません。C ++はこれについて衒学者であり、演算子のオーバーロードを可能にするため、演算子をオーバーロードする人々は、演算子の関係に関して期待できることをコードのユーザーに伝えるために専門用語を必要とするため、それはほとんど必要です。Javaは、コンパレータとhashCodeがequalsと一致していることについて話しますが、これが必要なすべてです。C ++は、<、>、==、<=、> =、割り当ての事後条件などを処理する必要があります。
C ++は、APIでこれに対して非常に純粋数学的なアプローチを採用しているため、すべてが単一の二項関係で定義されます。Javaはいくつかの点で親しみやすく、基本単位の定義(比較)が少し複雑であるが、そこから導かれるロジックが単純である3者間比較を好みます。また、ソートアルゴリズムが比較ごとにより多くの情報を取得することも意味します。これは、場合によっては便利です。例については、「オランダの旗」クイックソートの最適化を参照してください。これは、データに「同じ場所に」重複が多数ある場合に役立ちます。
その場合、3つの値のコンパレータは速度ゲインです。ただし、C ++は、並べ替えやおよびなどにコンパレータの一貫した定義を使用します。set
これは、3つの値のコンパレータからほとんどメリットがありません(1つの比較を保存する場合もあれば、そうでない場合もあります)。特定のまたは限られた潜在的な効率向上のために、彼らは彼らの素晴らしい一般的なインターフェースを複雑にしないことに決めたと思います。map
lower_bound