14

次のコードがあります。

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.

構造体のインスタンスを にマップしようとするとNodeintコンパイル エラーが発生しました。なんで?

4

6 に答える 6

23

マップのキーとして使用できるものを作成するには、を使用して比較できる必要がありますoperator<()。このような演算子をノードクラスに追加する必要があります。

struct Node
{
 int a;
 int b;

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

もちろん、実際の演算子が何をするかは、構造体にとって実際に比較が何を意味するかによって異なります。

于 2010-02-06T18:59:46.727 に答える
10

ノードオブジェクトを比較する方法をstd::mapに指示する必要があります。デフォルトでは、less演算子を使用してこれを実行しようとします。ただし、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を等しい(同じキー)と見なすことに注意して!(x<y)ください!(y<x)

于 2010-02-06T18:59:25.917 に答える
7

ノードタイプの比較を有効にするには、より小さい演算子を定義する必要があります。

struct Node
{
 int a;
 int b;
};

bool operator<(Node const& n1, Node const& n2)
{  
   // TODO: Specify condition as you need
   return ... ;
}

ここでは、ユーザー定義型のLessThanComparableの意味を確認できます。

別の解決策は、 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;

このようなデカップリングは煩わしさが少なく(ノードクラスにはまったく触れません)、より拡張可能なソリューションを実現するのに役立ちます。

于 2010-02-06T19:02:09.717 に答える
3

データをキーでソートする必要が本当にない場合は、新しい unordered_map を使用できます。

#include <unordered_map>

... 

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

これを機能させるには、最新のコンパイラが必要です。

UPDATENode Neilが指摘しているように、キー 付きの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 が言うように、ハッシュ衝突の場合にキーを比較するには operator== が必要です。

bool operator==(const Node & lhs, const Node & rhs)
{
    return lhs.a == rhs.a && rhs.b == rhs.b;
}

結局のところ、 std::map の方がはるかに使いやすいと思います。

于 2010-02-06T19:09:06.353 に答える
1

コンパイラ エラーを投稿していただけますか。何が問題なのか伝えるためのものです。

Nodeマップの要素を識別するために必要な比較演算子を実装していないため、エラーが発生すると思います。

于 2010-02-06T18:57:41.903 に答える