2012-04-23 15 views
2

std :: mapに必要なオペレータ<()メソッドに問題があります。私は次のように見える複合キーとして構造体を使用しています:私は4つの値を持つ複合キーを使用する導入が、私はオペレータのためにこれを達成する方法がわからないのでstd map複合キー

struct MyKey { 
    std::string string1; 
    std::string string2; 
    std::string string3; 
    unsigned int uint1; 

    friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
    { 
    return mk1.string1 < mk2.string1 && mk1.string2 < mk2.string2 && 
      mk1.string3 < mk2.string3 && mk1.uint1 < mk2.uint1; 
    } 
} 

<方法。一度に1つの値しか保存されていないことがわかりました。

誰でも正しい状態がどのように見えるか教えてください。

ありがとうございます!

答えて

8

標準ライブラリの連想コンテナはstd::mapstd::setstd::multisetstd::multimapとして、std::bitsetは、要素の順序がoperator<の実装がstrict weak orderingに従わなければならないことを意味Strict Weak Orderingに、従わなければならないことを要求しています。だから、一つの実施は、この可能性:

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    if (mk1.string1 != mk2.string1) 
     return mk1.string1 < mk2.string1; 

    else if (mk1.string2 != mk2.string2) 
     return mk1.string2 < mk2.string2; 

    else if (mk1.string3 != mk2.string3) 
     return mk1.string3 < mk2.string3; 

    else 
     return mk1.uint1 < mk2.uint1; 
} 

それともとしてそれを実装することができます。このソリューションで

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    auto const & t1 = std::tie(mk1.string1, mk1.string2, mk1.string3, mk1.uint1); 
    auto const & t2 = std::tie(mk2.string1, mk2.string2, mk2.string3, mk2.uint1); 
    return t1 < t2; 
} 

std::tie関数は2つのタプルt1と、それに渡される引数の参照のt1を作成し、代わりにの代わりにoperator<を使用してt1t2を比較してください。タプルのためのoperator<は辞書順—厳密-弱い順序付けが達成される要素。..

2

私はあなたがオペレータ<は必ずしも厳密弱い順序付けを実装していないという問題点があると思うを比較します。 が偽であり、B<Aも偽である組合せが多すぎます。ABMyKeyのオブジェクトです。これは、ABに等しいと解釈されます。

2
実装に問題が、それは考慮し、安定していないということです

...評価

return mk1.string1 < mk2.string1 && mk1.string2 < mk2.string2 && 
     mk1.string3 < mk2.string3 && mk1.uint1 < mk2.uint1; 

... { "a", "a", "a", 1 } < { "a", "b", "a", 1 } = a<a && ... = false && ... = false

...しかし{ "a", "b", "a", 1 } < { "a", "a", "a", 1 } = a<a && ... = false && ... = false

だから、等しくないにもかかわらずmapにあります。

作業溶液:それは一度だけ、必要な文字列の比較を行うことが簡潔かつ効率的です...

friend bool operator<(const MyKey& mk1, const MyKey& mk2) 
{ 
    int x; 
    return (x = mk1.string1.compare(mk2.string1)) ? x < 0 : 
      (x = mk1.string2.compare(mk2.string2)) ? x < 0 : 
      (x = mk1.string3.compare(mk2.string3)) ? x < 0 : 
      mk1.uint1 < mk2.uint1; 
}