不能在Map中插入不同的struct值



我使用Node来保存协调器的(x, y),并尝试将4个节点插入映射中。下面的代码只打印2个节点,为什么?

{0,0}, 0
{1,2}, 3

如果我用

改变重载操作符'<'的代码
bool operator<(const Node &ob) const
{
return x < ob.x or y < ob.y;
}

打印所有4个节点。我对操作员的理解<只影响键的顺序。>

#include <iostream>
#include <map>
template<typename T1, typename T2>
struct Node
{
T1 x;
T2 y;
Node(T1 x, T2 y): x(x), y(y) {}
bool operator<(const Node &ob) const
{
return x < ob.x and y < ob.y;
}

bool operator==(const Node &ob) const
{
return x == ob.x and y == ob.y;
}

};
int main()
{
std::map<Node<int, int>, int> map =
{
{{0, 0}, 0},
{{0, 1}, 1},
{{1, 0}, 2},
{{1, 2}, 3}
};
for (const auto &entry: map)
{
auto key = entry.first;
std::cout << "{" << key.x << "," << key.y << "}, " << entry.second << std::endl;
}
return 0;
}

std::map认为两个元素相等,如果对于两个键ab,比较器(在您的示例中是默认的std::less)满足

!comp(a, b) && !comp(b, a)

让我们检查一下你的箱子:

首先插入键Node<int, int>(0, 0),然后是键Node<int, int>(0, 1)。对于这些元素(以及您的operator<),以下内容成立:

!std::less(Node<int, int>(0, 0), Node<int, int>(0, 1))
&& !std::less(Node<int, int>(0, 0), Node<int, int>(0, 1)) 
=>
!(Node<int, int>(0, 0) < Node<int, int>(0, 1))
&& !(Node<int, int>(0, 1) < Node<int, int>(0, 0))
=>
!(0 < 0 && 0 < 1) && !(0 < 0 && 1 < 0)
=>
!(false && true) && !(false && false)
=> !false && !false
=> true

所以两个节点被认为是相等的,没有插入发生。对于Node<int, int>(1, 0)也是如此。

插入Node<int, int>(1, 2)有效,因为

!(0 < 1 && 0 < 2) && !(1 < 0 && 2 < 0)
=>
!(true && true) && !(false && false)
=>
!true && !false
=>
false && true
=>
false

您可以通过使用另一个operator<来解决这个问题,例如,正如评论中所说,通过使用std::tie

最新更新