为什么以下代码打印1
,即使我在地图中插入了两个元素?
#include <iostream>
#include <map>
#include <string>
#include <utility>
struct Foo
{
Foo(int bar, const std::string& baz)
: bar(bar)
, baz(baz)
{}
int bar;
std::string baz;
bool operator<(const Foo& rhs) const
{
if (bar < rhs.bar && baz < rhs.baz)
{
return true;
}
else
{
return false;
}
}
};
int main()
{
Foo first(0, "test");
Foo second(1, "test");
std::map<Foo, std::string> m;
m.insert(std::make_pair(first, "test"));
m.insert(std::make_pair(second, "test1"));
std::cout << m.size() << std::endl;
}
对insert()
的第二次调用表示我们已在地图中拥有该项目。为什么呢?
我的previous question由于拼写错误而被错误地关闭了。我知道insert
会告诉您该项目是否已经在容器中。
答案 0 :(得分:6)
地图insert()
使用您提供的operator<
来确定元素之间的等效性。如果a < b
和b < a
都为false,则认为这两个元素相等。
您的operator<()
不一致,因为它没有定义必要的strict weak ordering。例如,考虑a.bar < b.bar
和b.baz < a.baz
;然后a < b
为false且b < a
为false,因此地图相信a == b
。
在特定情况下,在比较first
和second
时,first.baz
和second.baz
都是"test"
,因此两个比较都返回false,元素被认为是平等的。
您需要以下内容:
bool operator<(const Foo& rhs) const
{
return std::tie(bar, baz) < std::tie(rhs.bar, rhs.baz);
}