2012-04-23 81 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; 
}