2012-04-23 112 views
2

我對運算符<()方法存在問題,這是std :: map所必需的。我使用的是結構爲複合鍵,看起來如下: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; 
    } 
} 

據介紹我想使用4個值的複合鍵,但我不知道如何做到這一點的操作<方法。我發現一次只能存儲1個值!

有人可以告訴我如何正確的條件是什麼樣子?

在此先感謝!

回答

8

標準庫的關聯容器std::mapstd::setstd::multisetstd::multimapstd::bitset要求元素的順序必須遵循Strict Weak Ordering,這意味着你的operator<實現必須遵守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函數創建兩個元t1並傳遞給它的參數引用的t1,然後使用重載的operator<代替std::tuple來比較t1t2。元組operator<比較元素按字典順序排列—嚴格 - 弱排序實現..

2

我認爲你有一個問題,運算符<不一定實現嚴格的弱排序。有太多的組合,其中A<B爲假,而B<A也爲false,其中ABMyKey對象。這被解釋爲A等於B

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

A工作液:它是簡潔高效的做每一個必要的字符串比較只有一次......

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; 
}