2012-01-07 25 views
0

std::set(またはstd::mapなど)が固有のキーを識別する方法を理解している問題があります。私がやろうとしています事はboost::shared_ptr内構造体オブジェクトをラップして、std::setコンテナ内のポインタを共有ストアです:std :: setとboost :: shared_ptr固有のキー識別の問題

のは、構造体がカラーであるとしましょう:

struct Color { 
    float r; 
    float g; 
    float b; 
}; 

その後コンテナと比較関数オブジェクト別のクラスで定義されている:

class AnotherClass { 

    typedef boost::shared_ptr<Color> ColorPtr; 

    public: 

     struct ColorCompare { 
      bool operator()(const ColorPtr &a, const ColorPtr &b) const { 
       return (a->r > b->r) && (a->g > b->g) && (a->b > b->b); 
      } 
     }; 

    private: 

     // Container definition 
     std::set<ColorPtr, ColorCompare> colors; 
}; 

上記のコードが一意に包まColor構造体に基づいてshared_ptrオブジェクトを識別するために失敗しています。私はいつも、std::setコンテナが2つのオブジェクトに対して比較関数を実行し、それらのどれもが他のものよりも大きくない、あるいはそれ以下でない場合、それらが等しいとみなすと考えました。ポインタのアドレスに基づいて実装されているので、私はデフォルトのshared_ptr::operator<()less<...>を使用できないことに注意してください。

私には何が欠けていますか?

P.S.私はshared_ptrの中に色をラッピングしています。ある時点で参照カウントを知る必要があります(そして、参照カウント1の色を取り除く必要があります。すなわち、std::setコンテナ自体によって参照されるだけです)。同じ結果を得るより良い方法はありますか?

+0

'weak_ptr'を保存し、' expired() 'であれば削除することができます。 – Xeo

+0

しかし、 'weak_ptr'だけが' shared_ptr'を監視しているわけではありませんか?だから私はまだいくつかの時点で 'shared_ptr'を保存したり、譲り渡したりする必要があります。提案thoをありがとう。 – Sim

+0

'weak_ptr :: lock'は新しい' shared_ptr'を作成します。 – Xeo

答えて

4

比較は厳密な弱い注文である必要がありますが、これはあなたのものではありません。 (?例えば、(1,0,0)と(0,1,0)命じているか)、これを行います。

return (a->r > b->r)         || 
     ((a->r == b->r) && (a->g > b->g))    || 
     ((a->r == b->r) && (a->g == b->g) && (a->b > b->b)); 

これは、要素のタプル上の標準辞書式順序です。

一般的にa->r == b->rの代わりに!(b->r > a->r)と書くと、互換性のある等価演算子に依存しないようにすることができますが、この単純なfloatの場合は問題ありません。

ちなみに、structは必要ありませんが、static bool ColorCompare(...);の機能を宣言するだけです。もう1つの方法は、struct Colorに直接operator<を定義してすべてを自己完結型にすることです(スマートなポインタ用の汎用逆参照コンパレータが必要です)。

+0

'' Color''の ''演算子 ''は、IIRCでは動作しません。これは 'shared_ptr'は比較を実際のオブジェクトに転送せず、単純にポインタを比較します。また、これは、厳密な弱い順序の正しい実装がいかに醜いかを再び示す。 [うれしい私の解決策を見つけた!](@stackoverflow.com/questions/6218812/implementing-comparision-operators-via-tuple-and-tie-a-good-idea) – Xeo

+0

@ Xeo:あなたはまだ必要です一般的な "共有ポインタバイ・バリュー・コンパレータ"ですが、これはポインティの内部に関係なく実行できます。私はメモを付け加えた。ところで、良いリンク。 –

+0

それは問題だった - ありがとう。私はあなたの実装を試みたが、いくつかの奇妙なstl例外 "無効な演算子<"を取得しました。それから私は[この回答](http://stackoverflow.com/a/979768/454230)を試して、厳密な弱い順序アルゴリズムがうまくいくようだ。 – Sim

関連する問題