代码之家  ›  专栏  ›  技术社区  ›  CodingLab

是否无法将stl映射与结构一起使用?

  •  14
  • CodingLab  · 技术社区  · 16 年前

    我有以下代码:

    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.
    

    当我试图映射我的结构的实例时 Node int

    5 回复  |  直到 7 年前
        1
  •  23
  •   anon anon    16 年前

    要使某个东西可用作地图中的键,您必须能够使用 operator<()

    struct Node
    {
     int a;
     int b;
    
     bool operator<( const Node & n ) const {
       return this->a < n.a;   // for example
     }
    };
    

    当然,实数运算符的作用取决于比较对结构的实际意义。

        2
  •  10
  •   sellibitze    16 年前

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

    自由函数示例:

    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视为相等(相同键)。

        3
  •  7
  •   Community Mohan Dere    9 年前

    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 另一种方法是比较两种成分, 节点::a Node::b . 然后,定义不同类型的贴图:

    typedef std::map<Node, int, NodeLessThan>    node_map_t;
    typedef std::map<Node, int, NodeLessThanByA> node_map_a_t;
    

        4
  •  3
  •   Manuel    16 年前

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

    #include <unordered_map>
    
    ... 
    
    std::tr1::unordered_map<Node, int> aa;  // Doesn't require operator<(Node, Node)
    

    更新 正如Neil指出的,如果您想要一个无序的带有 Node

    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毕竟更容易使用。

        5
  •  1
  •   Dario    16 年前

    你能把编译器的错误贴出来吗?他们是想告诉你的 , .

    我猜你的错误发生在 Node 不实现映射所需的比较运算符以标识其元素。

        6
  •  0
  •   honk    7 年前

    作为一个 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;
    }
    

    输出:

    请根据您的需要更换lambda表达式的主体。

    Code on Ideone