2012-03-20 4 views
2

自分で定義したクラスオブジェクトのセットにSTL set::find()を使用することについて少し混乱します。カスタムクラスオブジェクトに対してset :: find()を動作させるには?

私のクラスには2つ以上のアイテム(3/4/5など)が含まれていますので、lessにどのようにオーバーロードできますか?

I微細以下の通りであると作業3変数のための試み:

return((a1.i < a2.i) || 
    (!(a1.i > a2.i) && (a1.f < a2.f)) || 
    (!(a1.i > a2.i) && !(a1.f > a2.f) && (a1.c < a2.c))); 

場合、a1、及びa2はクラスオブジェクトであり、(ifcクラスメンバーです)。

今、これをn個のメンバーに一般化したいと思いますが、find()は必ずしも機能しません。

私はSTLの詳細な文書を見て、set::find()がどのように実装されているのか、なぜそれほど少ないオペレータオーバーロード(<)が必要なのかを試してみました。

私はsgiとmsdnのドキュメントを参照しましたが、実装の詳細についてはset::find()もありませんでした。

set::find()の実装で何が間違っていますか?

+1

'std :: set :: find'がどのように実装されているのか気になるのはなぜですか?どうやって使うの? –

+0

findの実装は指定されていませんが、厳密な要件が標準で指定されています。たとえば、C++ 11標準では、23.2.4を参照してください。 – juanchopanza

+0

std :: set :: findのデフォルトの大文字と小文字を使用して、使用しているコンパイラの関数にステップインすることができます。 – DumbCoder

答えて

4

オブジェクトの厳密な順序付けを定義する必要があります。だからあなたのオブジェクトがnメンバーa_1で構成されている場合.. a_nすべてが厳格な自分自身を注文、何を行うことができますすることである持っている:ブーストまたはC++ 11のいずれかである場合 :

bool operator< (const TYPE &rhs) { 
    if (a_1 < rhs.a_1) return true; else if (a_1 > rhs.a_1) return false; 
    if (a_2 < rhs.a_2) return true; else if (a_2 > rhs.a_2) return false; 
    ... 
    if (a_n < rhs.a_n) return true; 
    return false; 
} 

編集をあなたの答えでは、あなたは本当にstd::tie/boost::tieという方法で行くべきだとLuc Dantonは答えました。はるかにクリーンです。

1

あなたoperator <はまたその

struct Data 
{ 
    bool operator < (const Data& right) const 
    { 
    return((this.i < right.i) || 
     (!(this.i > right.i) && (this.f < right.f)) || 
     (!(this.i > right.i) && !(this.f > right.f) && (this.c < right.c))); 
    } 
} 

のように、与えられたものとすべてのオブジェクトを比較することが可能であるべきで、あなたの比較アルゴリズムが、それはケースを考慮していないdoeesので、疑わしいに見える、とき

this.i == right.i 

this.f == right.f 

実際にはに興味を持ってはいけません。の実装。コンパイラからコンパイラに変更することができ、将来変更することができます。あなたのプログラムは、コンテナのインタフェースについてのみ仮定してください。決しての実装にはなりません。

1

これは部分的な答えですが、STLの詳細なドキュメントはthe website of SGIにあります。

+1

実際には、SGI STLと標準ライブラリにあるものとの間にかなりの違いがあります。 cppreference.comのようなものがおそらくもっといいアイデアかもしれませんし、誰かがstandardeseを学んでいれば、標準を直接使うこともできます:[このページ]からリンクされているn3337を参照してください(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012 /#mailing2012-01) – bames53

+0

はい、そうです。しかし、私は* STLのドキュメント*が行うことを理解しましたが、私はまだスタンダードライブラリ自体についてのリソースにリンクしておく必要があります。 –

2

std :: set要素比較関数は、要素ドメインでStrict Weak Orderingリレーションを定義する必要があります。この定義を使用して、compare(a、b)がfalseでcompare(b、a)もfalseの場合、2つの要素が等価であると言うことができます。 std :: findはこの仮定を使用して実装できます。
あなたがここで詳細を見つけることができます。http://www.sgi.com/tech/stl/set.htmlhttp://www.sgi.com/tech/stl/StrictWeakOrdering.html

4

を簡単にあなたのメンバーの辞書式順序を取得するためにタプルを使用することができます。

return std::tie(lhs.i, lhs.f, lhs.c) < std::tie(rhs.i, rhs.f, rhs.c); 

これは、すべてのメンバーは、例えば、同等のタイプのものであることが必要ですlhs.i < rhs.iが理にかなっています。

std::tiestd::tupleはC++ 11でのみ使用できるため、C++ 03では、 Boost.Tupleはboost::tieを提供します(boost::tuplestd::tupleと同じ順序付けを使用します)。

これはどこに行くべきかについては、operator<に入れておくことが慣例です(この後は、最初は簡単に注文できるようにtieを使用しています)。かなり頻繁にこの演算子は友人となりますので、これは次のようになります。あなたがoperator<の実装はすべてのfooのメンバー(またはのために重要で、少なくともそれらをリストする必要があるとして、それは完全に自動化ではありません見ることができるように

class foo { 
public: 
    /* public interface goes here */ 

    // declaration of non-member friend operator 
    // if it doesn't need to be a friend, this declaration isn't needed 
    friend 
    bool operator<(foo const& lhs, foo const& rhs); 

private: 
    T t; 
    U u; 
    V v; 

}; 

bool operator<(foo const& lhs, foo const& rhs) 
{ 
    // could be boost::tie 
    return std::tie(lhs.t, lhs.u, lhs.v) < std::tie(rhs.t, rhs.u, rhs.v); 
} 

順序)、2回。私が恐れるより良い方法はありません。

operator<を提供する代わりに、foostd::lessを特化することができますが、これはちょっとエキゾチックで、好ましい方法ではありません。

struct foo_ordering { 
    bool operator()(foo const& lhs, foo const& rhs) const 
    { 
     /* implementation as before, but access control/friendship 
      has to be planned for just like for operator< */ 
    } 
}; 
:まだ意味をなさない順序が fooの拡張インタフェースの一部にする場合(例えば、標準的な1なしで理にかなっている、複数の発注があるかもしれません)、そして好ましい方法はファンクタを書くことです

次に、たとえばstd::set<foo, foo_ordering>

それはstd::setまたはその他の連想コンテナで使用されている場合の順序を形成するものに関係なく(どちらかoperator<std::less<foo>またはファンクタを通じて)かかることに注意してください(デフォルトの例でstd::set<T>は順番にでoperator<を使用していますstd::less<T>を使用していますデフォルト)、それはいくつかの厳格な基準に従わなければなりません。つまり厳密な弱い順序でなければなりません。しかし、自分自身で順序付けを行うために使用されるすべてのメンバがSW順序を持つ場合、結果として得られる辞書順はSW順序です。

+0

+1すてきな解決策ですが、私はOPの演算子の式を見て頭を悩ましています。私はそれがあなたと同等であるとは確信していません: – juanchopanza

+0

@juanchopanza広告としてこれは辞書編集の順序付けを提供します。 OPがそれを必要とするかどうか私はどちらかと言うことができません:) –

関連する問題