我遇到了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个值的复合键,但我不知道如何为运算符&lt; 方法实现此目的。我发现一次只存储1个值!
有人可以告诉我正确的情况如何?
提前致谢!
答案 0 :(得分:8)
标准库的关联容器,例如std::map
,std::set
,std::multiset
,std::multimap
,std::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
,然后比较t1
和{{1}使用重载t2
代替operator<
。元组的operator<按字典顺序比较元素 - 实现严格弱序排列。
答案 1 :(得分:2)
我认为你有一个问题,即运营商&lt;不一定实现严格的弱排序。 A<B
为假且B<A
也为假的组合太多,其中A
和B
为MyKey
个对象。这被解释为A
等于B
。
答案 2 :(得分: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;
}