2011-07-04 5 views
60

あるクラスのオブジェクトを別のクラスのオブジェクトにマップしたいと考えています。私がキーとして使用したいクラスは私によって書かれたものではなく、いくつかの値を持つ単純なstructです。 std :: mapは内容を注文しています。どのようにして、どのような任意のクラスをキーとして使用するか、定義する必要のある一連の要件(演算子とは関係ありません)があるかどうか疑問に思っていました。std :: mapキークラスが満たしていなければならない要件は、有効なキーである必要がありますか?

もしそうなら、演算子マップの使用を実装するクラスのラッパーを作成できます。私は最初に実装する必要があることを知るだけで、クラスI found onlineのリファレンスはどれも指定しません。

答えて

54

キーを必要としているすべては、それがコピー可能と割り当て可能であることです。 マップ内の順序は、 テンプレートの3番目の引数(およびコンストラクタが使用されている場合はその引数)によって定義されます。この デフォルトはstd::less<KeyType>です。デフォルトは<の演算子で、 ですが、デフォルトを使用する必要はありません。それはすなわち真CmpMyType()(a, b )を返した場合、CmpMyType()(b, a)はfalseを返す必要があり、かつ は両方falseを返す場合、厳密な順序付けを定義しなければならないことを

struct CmpMyType 
{ 
    bool operator()(MyType const& lhs, MyType const& rhs) const 
    { 
     // ... 
    } 
}; 

注:ジャスト(好ましくは機能オブジェクトとして)比較 演算子を書きます要素は等しいと見なされます( 同じ等価クラスのメンバー)。

+0

+1確かに、実際の要件であるコピー可能で割り当て可能です。 – juanchopanza

2

と同じです。setと同じです。クラスは、「より小さい」という精神で厳密な順序付けをしていなければなりません。適切なoperator<をオーバーロードするか、カスタム述部を指定してください。いずれの2つのオブジェクトaおよびbについても、!(a<b) && !(b>a)が等しいと見なされます。

マップコンテナは実際には、その順序によって提供される順序ですべての要素を保持します。これは、キー値によるO(ログn)ルックアップおよび挿入時間の達成方法です。

3

答えは実際には "比較"テンプレート引数の説明の下でリンクしています。

唯一の要件は、Compare(デフォルトではless<Key>です。これはデフォルトでoperator<を使用してキーを比較する)は「厳密な弱い順序」でなければなりません。あなたはこのような、たとえば、オペレータ<を定義する必要が

18

struct A 
{ 
    int a; 
    std::string b; 
}; 

// Simple but wrong as it does not provide the strict weak ordering.  
// As A(5,"a") and A(5,"b") would be considered equal using this function. 
bool operator<(const A& l, const A& r) 
{ 
    return (l.a < r.a) && (l.b < r.b); 
} 

// Better brute force. 
bool operator<(const A& l, const A& r) 
{ 
    if (l.a < r.a) return true; 
    if (l.a > r.a) return false; 

    // Otherwise a are equal 
    if (l.b < r.b) return true; 
    if (l.b > r.b) return false; 

    // Otherwise both are equal 
    return false; 
} 

// This can often be seen written as 
bool operator<(const A& l, const A& r) 
{ 
    // This is fine for a small number of members. 
    // But I prefer the brute force approach when you start to get lots of members. 
    return (l.a < r.a) || 
      ((l.a == r.a) && (l.b < r.b)); 
} 
+0

これはひどい比較演算子です。 –

+1

それは間違っていただけではありませんでした。マップコンテナが要求する「厳密な弱い順序」を提供しませんでした。上記のブルートフォースバージョンを提供して補償してください。 A(5、 "A")とA(5、 "B")の違いを比較する –

+0

右の簡単な例を載せて、それを台無しにしてしまいました。例を修正してくれたMartinに感謝します。 –

関連する問題