struct Node
{
int a;
int b;
};
Node node;
node.a = 2;
node.b = 3;
map<int, int> aa;
aa[1]=1; //O.K.
map<Node, int> bb;
bb[node]=1; //Compile Error
当我尝试将结构映射到int时,它给了我一个编译错误。 为什么? 谢谢!
答案 0 :(得分:23)
要将某个内容用作地图中的键,您必须能够使用operator<()
进行比较。您需要将这样的运算符添加到节点类:
struct Node
{
int a;
int b;
bool operator<( const Node & n ) const {
return this->a < n.a; // for example
}
};
当然,真正的算子所做的取决于比较对你的结构实际意味着什么。
答案 1 :(得分:9)
你必须告诉std :: map如何比较Node对象。默认情况下,它尝试使用小于运算符。但是你没有为Node提供任何运算符。最简单的解决方案是提供一个。
自由功能示例:
bool operator<(Node const& n1, Node const& n2)
{
return n1.a<n2.a || (n1.a==n2.a && n1.b<n2.b);
}
请注意,对于任何一对节点对象x,y与!(x<y)
和!(y<x)
,地图会将x和y视为相等(相同的键)。
答案 2 :(得分:6)
您需要定义less-than运算符以启用Node类型的比较:
struct Node
{
int a;
int b;
};
bool operator<(Node const& n1, Node const& n2)
{
// TODO: Specify condition as you need
return ... ;
}
您可以在此处查看LessThan Comparable对用户定义类型的含义。
替代解决方案是基于std::binary_function定义仿函数。从设计的角度来看,此选项具有优势,因为比较与Node
类有效地分离。这样就可以定义专门用不同比较条件(仿函数)的地图。
#include <map>
struct Node
{
int a;
int b;
};
struct NodeLessThan
: public std::binary_function<Node, Node, bool>
{
bool operator() (Node const& n1, Node const& n2) const
{
// TODO: your condition
return n1.a < n2.a;
}
};
int main()
{
Node node;
node.a = 2;
node.b = 3;
typedef std::map<Node, int, NodeLessThan> node_map_t;
node_map_t bb;
bb[node] = 1;
}
因此,您可以定义比NodeLessThan
更多的比较,例如使用不同的条件,或仅比较Node::a
另一个比较两个组件Node::a
和Node::b
。然后,定义不同类型的地图:
typedef std::map<Node, int, NodeLessThan> node_map_t;
typedef std::map<Node, int, NodeLessThanByA> node_map_a_t;
这种解耦不那么具有侵入性(根本不会触及Node类),有利于实现更具可扩展性的解决方案。
答案 3 :(得分:3)
如果您不需要按键对数据进行排序,则可以使用新的unordered_map:
#include <unordered_map>
...
std::tr1::unordered_map<Node, int> aa; // Doesn't require operator<(Node, Node)
你需要一个最近的编译器来实现这个目的。
<强>更新强>
正如Neil所指出的,如果你想要一个带有Node
个密钥的unordered_map,你需要一个专门的哈希函数。
struct NodeHash : std::unary_function<Node, size_t>
{
size_t operator()(Node const & node) const
{
return static_cast<size_t>(node.a + 1) * static_cast<size_t>(node.b + 1);
}
};
然后地图变成:
std::tr1::unordered_map<Node, int, NodeHash> aa;
另外,正如sellibitze所说,在哈希冲突的情况下需要运算符==来比较密钥:
bool operator==(const Node & lhs, const Node & rhs)
{
return lhs.a == rhs.a && rhs.b == rhs.b;
}
所以我猜std :: map毕竟更容易使用。
答案 4 :(得分:1)
你能否发布编译错误 - 他们打算告诉你,什么是错的。
我猜你的错误发生了,因为Node
没有实现地图所需的比较运算符,以便识别它的元素。
答案 5 :(得分:0)
当std::map按其键排序时,您必须定义如何比较两个Node
对象。由于C++11,您还可以使用lambda expression而不是定义比较运算符。结果,您可以使代码简短,如下所示:
int main() {
Node node{ 2, 3 };
auto comp = [](const Node& n1, const Node& n2) {
return n1.a < n2.a || (n1.a == n2.a && n1.b < n2.b);
};
std::map<Node, int, decltype(comp)> bb(comp);
bb[node] = 1;
for (auto const &kv : bb)
std::cout << kv.first.a << ", " << kv.first.b << ": " << kv.second << std::endl;
return 0;
}
输出:
2,3:3
请根据需要替换lambda表达式的正文。