C++ 是否不可能将STL映射与结构一起用作键?

C++ 是否不可能将STL映射与结构一起用作键?,c++,dictionary,stl,containers,stdmap,C++,Dictionary,Stl,Containers,Stdmap,我有以下代码: struct Node { int a; int b; }; Node node; node.a = 2; node.b = 3; map<int, int> aa; aa[1]=1; // OK. map<Node, int> bb; bb[node]=1; // Compile error. struct节点 { INTA; int b; }; 节点; 节点a=2; 节点b=3; 地图aa; aa[1]=1;//好啊 地图bb; bb[

我有以下代码:

struct Node
{
  int a;
  int b;
};

Node node;
node.a = 2;
node.b = 3;

map<int, int> aa;
aa[1]=1; // OK.

map<Node, int> bb;
bb[node]=1; // Compile error.
struct节点
{
INTA;
int b;
};
节点;
节点a=2;
节点b=3;
地图aa;
aa[1]=1;//好啊
地图bb;
bb[节点]=1;//编译错误。

当我试图将struct
节点的一个实例映射到
int
时,我得到了一个编译错误。为什么?

你能发布编译器错误吗?他们的目的是告诉你出了什么问题


我猜您的错误是因为
节点
没有实现映射所需的比较运算符来识别其元素。

您必须告诉std::map如何比较节点对象。默认情况下,它尝试使用小于运算符来执行此操作。但您并没有为节点提供任何小于运算符。最简单的解决办法是提供一个

自由函数示例:

bool operator<(Node const& n1, Node const& n2)
{
    return n1.a<n2.a || (n1.a==n2.a && n1.b<n2.b);
}

bool操作符要将某个对象用作映射中的键,您必须能够使用
operator对其进行比较。您需要定义小于运算符以启用节点类型的比较:

struct Node
{
 int a;
 int b;
};

bool operator<(Node const& n1, Node const& n2)
{  
   // TODO: Specify condition as you need
   return ... ;
}
因此,您可以定义更多的比较,而不仅仅是
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;
typedef std::map node\u map\t;
typedef std::map node\u map\u t;

这种分离不太麻烦(根本不涉及节点类),有利于实现更具可扩展性的解决方案。

如果您真的不需要按键对数据进行排序,您可以使用新的无序映射:

#include <unordered_map>

... 

std::tr1::unordered_map<Node, int> aa;  // Doesn't require operator<(Node, Node)
然后地图变成:

 std::tr1::unordered_map<Node, int, NodeHash> aa;
所以我想std::map毕竟更容易使用。

由于a是按键排序的,所以必须定义如何比较两个
节点
对象。因为您也可以使用而不是定义比较运算符。因此,您可以保持代码的简短,如下所示:

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;
}
intmain(){
节点{2,3};
自动补偿=[](常数节点和n1,常数节点和n2){
返回n1.a你是对的吗?你不需要operator@Manuel我认为您已经很好地说明了编写一个好的哈希函数有多么困难:-)对于(a,b)对(0,1)和(1,0),您的函数将具有相同的值(1)对于许多其他对也是如此。无序映射不也需要运算符==作为键吗?@Neil-是的,这确实很难。标准不应该提供一种简单的方法来处理这个问题吗?可能是一个函数“mem_hash”,您可以将块的地址和大小(以字节为单位)传递给它,然后返回该块内容的哈希。@Neil-看起来像(a+1)*(b+1)作为散列函数工作得更好。在我的测试()中,配备此散列函数的tr1::unordered_集执行查找操作的速度是std::set的两倍。@Steve更准确地说,指针可能无法与<-相比较,这取决于它们指向什么。是的,我的意思是,“同一类型的指针通常与

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;
bool operator==(const Node & lhs, const Node & rhs)
{
    return lhs.a == rhs.a && rhs.b == rhs.b;
}
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;
}