23

最初に値でソートし、次に別の値でソートすることになっている次の operator< があります。

    inline bool operator < (const obj& a, const obj& b) 
    {
        if(a.field1< b.field1)
            return true;
        else
            return a.field2 < b.field2;
    }

これは正しくなく、メンバー変数に対して 3 番目の比較テストを行わないと実行できないと感じていますが、これが機能しない例は見つかりません。では、これは本当に期待どおりにソートされるのでしょうか? ありがとう

編集:私はそれを次のようにコーディングしたでしょう:

    inline bool operator < (const obj& a, const obj& b) 
    {
        if(a.field1< b.field1)
            return true;
                    else if(a.field1> b.field1)
            return false;
        else
            return a.field2 < b.field2;
    }

違いはありますか?私の経験からは正しいが、最初のものよりも長いことを知っているので、私は尋ねています

4

6 に答える 6

42

全部一人でやりたいです。

の値が等しいObj::field2場合にのみ、の値を比較する必要があります。Obj::field1

わかりやすい方法:

/* This will meet the requirements of Strict-Weak-Ordering */

if (a.field1 != b.field1) return a.field1 < b.field1;
else                      return a.field2 < b.field2;

正しい(推奨される)方法:

それを実装する「正しいoperator<」方法は、フィールドを比較するためだけに使用されます。以下は、実際よりも複雑に見えます。

ただし、以前に作成したわかりやすい例と同じ結果が得られます。

return a.field1 < b.field1 || (
  !(b.field1 < a.field1) && a.field2 < b.field2
);

operator<多くの頭痛を引き起こさずに実装する方法が必要ですか?

C ++ 11

以下の例のように、複数のフィールドがすでに定義されているSTLstd::tupleから使用できます。operator<

#include <utility>

...

inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
  return std::tie (lhs.field1, lhs.field2) < std::tie (rhs.field1, rhs.field);
}

C ++ 03

コンパイラがまだC++11をサポートしておらず、std::pair代わりに使用できる各オブジェクトの2つのフィールドを比較するだけでよい場合。

の理由std::make_pairは、を使用した前の例と同じstd::tieです。

#include <utility>

...

inline bool
operator< (Obj const& lhs, Obj const& rhs)
{
  return std::make_pair (lhs.field1, lhs.field2)
       < std::make_pair (rhs.field1, rhs.field2);
}

を使用std::pairすると、メンバーのコピーを作成する必要がありますが、状況によっては望ましくありません。

これは本当にお勧めの練習ですか?

詳細については、以下の質問/回答を参照してください。ただし、要約すると、c ++ 11のアプローチでは、それほど多くのオーバーヘッドは発生せず、実装は非常に簡単です。

于 2012-07-03T13:55:08.817 に答える
8

a.field1より大きいb.field1a.field2より小さい場合に何が起こるかを考えてくださいb.field2。そのような状況では、あなたはあなたが望むものではないものだけに基づいて比較します。field2

field2フィールドが等しい場合にのみ機能させたいfield1ので、探しているのは(擬似コード)のようなものです。

if a.field1 < b.field1: return true
if a.field1 > b.field1: return false
# field1s is equal here.
return a.field2 < b.field2
于 2012-07-03T13:56:30.437 に答える
4

いいえ。キャッチする必要もあり(a.field1 > b.field1)ます。

これは厳密な弱順序ではありません。これは、を与える(1,2) < (2,1)だけでなく、も与えるから(2,1) < (1,2)です。

于 2012-07-03T13:54:29.807 に答える
2

明示的な分岐を避けるために、論理短絡規則に依存するバージョンを次に示します。

template<typename T>
bool operator< (T const& a, T const& b)
{
        return (
                 ( a.field1 < b.field1 ) || (( a.field1 == b.field1 ) &&
                 ( a.field2 < b.field2 ))
        );
}

これは、プリミティブ型field1operator==. これを 2 つ以上のフィールドに入力するのは面倒ですがstd::lexicographical_compare、クラスがいくつかのタイプとサイズobjのフィールドを 内に格納する場合に使用できますstd::array<T, N>TN

template<typename T, int N>
struct obj
{
    std::array<T, N> field;
};

bool operator< (obj const& a, T const& b)
{
        return std::lexicographical_compare(
            a.field.begin(), a.field.end(), 
            b.field.begin(), b.field.end()
        );
}

演算子の追加と、クラス タイプの自動化について説明しているドラフト ペーパーN3326があることに注意してください。==<

于 2012-07-03T14:41:55.010 に答える