厳密な弱い順序付けの概念を満たすように、n-タプル(たとえば、3-タプル)にoperator<
を定義する方法は? boostライブラリにoperator<
が正しく定義されたタプルクラスがあることは知っていますが、何らかの理由で使用できません。
if (a1 < b1)
return true;
if (b1 < a1)
return false;
// a1==b1: continue with element 2
if (a2 < b2)
return true;
if (b2 < a2)
return false;
// a2 == b2: continue with element 3
if (a3 < b3)
return true;
return false; // early out
これは、a1が最も重要でa3が最も重要でないことによって要素を並べ替えます。
これは無限に続けることができます。これをTのベクトルに適用し、a [i] <a [i + 1]/a [i + 1] <a [i]の比較を繰り返します。アルゴリズムの別の表現は、「等しいときにスキップしてから比較する」です。
while (i<count-1 && !(a[i] < a[i+1]) && !(a[i+1] < a[i])
++i;
return i < count-1 && a[i] < a[i+1];
もちろん、比較にコストがかかる場合は、比較結果をキャッシュすることをお勧めします。
[編集]間違ったコードを削除
[編集] operator<
だけではない場合、パターンを使用する傾向があります
if (a1 != b1)
return a1 < b1;
if (a2 != b2)
return a2 < b2;
...
これは、2つのオブジェクト間の関係を定義する数学用語です。
その定義は:
F(x、y)とf(y、x)の両方がfalseの場合、2つのオブジェクトxとyは同等です。オブジェクトは常に(非反射性不変量によって)それ自体と等価であることに注意してください。
C++に関しては、これは、特定のタイプの2つのオブジェクトがある場合、演算子<と比較すると、次の値を返す必要があることを意味します。
X a;
X b;
Condition: Test: Result
a is equivalent to b: a < b false
a is equivalent to b b < a false
a is less than b a < b true
a is less than b b < a false
b is less than a a < b false
b is less than a b < a true
同等/少ないをどのように定義するかは、オブジェクトのタイプに完全に依存します。
正式な定義:
厳密な弱い順序付け
コンピュータサイエンス:
厳密な弱い順序付け
オペレーターとの関係:
コンパレータ
...非常に古い質問に対する新しい回答ですが、既存の回答はC++ 11からの簡単な解決策を見逃しています...
C++ 11以降では、データの保存に使用できる _std::Tuple<T...>
_ が提供されます。 Tuple
sには一致する _operator<
_ があり、最初に左端の要素を比較し、結果が明確になるまでタプルに沿って機能します。 strict weak ordering を提供するのに適しています。 _std::set
_ および _std::map
_ 。
他の変数(struct
のフィールドなど)にデータがある場合は、 std::tie()
を使用してタプルof references。次に、別のタプルと比較できます。これにより、ユーザー定義のclass
/struct
タイプの特定のメンバーデータフィールドに_operator<
_を簡単に記述できます。
_struct My_Struct
{
int a_;
double b_;
std::string c_;
};
bool operator<(const My_Struct& lhs, const My_Struct& rhs)
{
return std::tie(lhs.a_, lhs.b_, lhs.c_) < std::tie(rhs.a_, rhs.b_, rhs.c_);
}
_
単に適切に定義されたoperator <()が既にある3要素ベクトルを使用するだけで済みます。これには、何もしなくてもN要素に拡張できるという利点があります。
ブーストバージョンを使用できない場合でも、コードにニックを入れることができるはずです。私はこれをstd :: pairからニックネームを付けました-3タプルは私が推測するのと同様になります。
return (_Left.first < _Right.first ||
!(_Right.first < _Left.first) && _Left.second < _Right.second);
編集:数人が指摘したように、コードで使用するために標準ライブラリからコードを盗む場合、これらの名前は予約されているので、アンダースコアが前面にあるものの名前を変更する必要があります。