カスタムコンパレータを使用してC ++でpriority_queueを宣言する


83

コンパレータ関数(ノードクラスの外部)としてpriority_queue of nodesを使用して、を宣言しようとしbool Compare(Node a, Node b)ています。

私が現在持っているものは:

priority_queue<Node, vector<Node>, Compare> openSet;

どういうわけか、私は得ています Error: "Compare" is not a type name

宣言をに変更する priority_queue <Node, vector<Node>, bool Compare>

私にくれます Error: expected a '>'

私も試しました:

priority_queue<Node, vector<Node>, Compare()> openSet;
priority_queue<Node, vector<Node>, bool Compare()> openSet;
priority_queue<Node, vector<Node>, Compare<Node, Node>> openSet; 

どうすれば正しく宣言できますpriority_queueか?

回答:


110

次のように、クラスCompareを宣言してオーバーロードoperator()する必要があります。

class Foo
{

};

class Compare
{
public:
    bool operator() (Foo, Foo)
    {
        return true;
    }
};

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, Compare> pq;
    return 0;
}

または、何らかの理由でクラスとして作成できない場合は、次のように使用できますstd::function

class Foo
{

};

bool Compare(Foo, Foo)
{
    return true;
}

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, std::function<bool(Foo, Foo)>> pq(Compare);
    return 0;
}

1
完璧、まさに私が探していたもの。別のクラスを作るとは思ってもみませんでした。最初の例はより良いスタイルと見なされますか?
Steven Morad 2013

2
@StevenMorad、私はオーバーロードされたクラスを使用することを好みますoperator()、それはより単純に見えます。
awesoon 2013

1
@soonなぜ演算子()をオーバーロードするのですか?これは、priority_queuesが内部でどのように実装されているかに関連していますか?>または<のオーバーロードは直感的に意味がありますが、()演算子はそれほど意味がありません
Piyush 2016年

2
@Piyush、質問はカスタムコンパレータをに渡すことについてpritority_queueです。質問によると、operator<組み込みのstd::lessコンパレータをオーバーロードして使用することは可能bool Compare(Node a, Node b)ですが、クラスの外部で宣言Nodeされています。
awesoon 2016年

1
私はこの答えに戻ってきます、おそらく今50回のように、私は構文を決して思い出せません
Rockstar5645

48

受け入れられた答えは、クラスまたはastd::functionをコンパレータとして使用する必要があるとあなたに信じさせます。本当じゃない!以下のようcute_ptrの答えを示して、あなたは、コンストラクタへの関数ポインタを渡すことができます。ただし、そのための構文は、そこに示されているものよりもはるかに単純です。

class Node;
bool Compare(Node a, Node b);

std::priority_queue<Node, std::vector<Node>, decltype(&Compare)> openSet(Compare);

つまり、関数の型を明示的にエンコードする必要はありませんdecltype。を使用して、コンパイラにエンコードさせることができます。

これは、コンパレータがラムダの場合に非常に役立ちます。を使用する以外の方法でラムダのタイプを指定することはできませんdecltype。例えば:

auto compare = [](Node a, Node b) { return a.foo < b.foo; }
std::priority_queue<Node, std::vector<Node>, decltype(compare)> openSet(compare);

1
これは素晴らしいです、ここに潜在的な罠(問題)があるかどうか疑問に思います。この回答がより多くの可視性と議論を得るのを見たいと思います。
Apollysはモニカ・サポート

1
@Apollys:私はこのメソッドを定期的に使用しています(通常Compareはラムダであり、宣言を書くことは不可能です)、トラップについては知りません。
CrisLuengo18年

ラムダ関数に対してこれを行う場合、ラムダ関数の本体をどこに配置しますか?あなたはそれが変数に格納しますf、あらかじめ、次に交換するComparef
EricAuld19年

@EricAuld:はい、のCompareようにラムダ関数にすることができますauto Compare = [](){};。ただしdecltype(Compare)、ではなく、を使用する必要がありますdecltype(&Compare)
CrisLuengo19年

こんにちはクリス、これは素晴らしいです、私はpriority_queueのdecltypeで使用するいくつかのフォーマットを探していました、そしてクラスを宣言せずに、あなたは完璧な答えを与えました!ありがとう!
アマンダワン

16

3番目のテンプレートパラメータは、operator()(Node,Node)オーバーロードしたクラスである必要があります。したがって、次の方法でクラスを作成する必要があります。

class ComparisonClass {
    bool operator() (Node, Node) {
        //comparison code here
    }
};

次に、このクラスを次のように3番目のテンプレートパラメーターとして使用します。

priority_queue<Node, vector<Node>, ComparisonClass> q;

13
演算子メソッドはパブリックである必要があります。
knezi 2017年

3番目のテンプレートはクラスである必要はありません。関数のタイプにすることができます。
Cris Luengo 2018

cpluplusによると:これは関数ポインタまたは関数オブジェクトである可能性があります
Benav

9

あなたの質問に直接答える:

priority_queue使用して、ノードのを宣言しようとしていますbool Compare(Node a, Node b) as the comparator function

私が現在持っているものは:

priority_queue<Node, vector<Node>, Compare> openSet;

何らかの理由で、エラーが発生します:

"Compare" is not a type name

コンパイラは何が問題なのかを正確に伝えています。これCompareは型名ではなく、2つを取りNodes、を返す関数のインスタンスですbool
必要なのは、関数ポインタ型を指定することです。
std::priority_queue<Node, std::vector<Node>, bool (*)(Node, Node)> openSet(Compare)


これはまさに私がpriority_queue宣言で関数を与えるために探しているものです、ありがとう!
アマンダワン

4

ラムダ関数を使用することもできます。

auto Compare = [](Node &a, Node &b) { //compare };
std::priority_queue<Node, std::vector<Node>, decltype(Compare)> openset(Compare);

2

これが誰かを助ける場合:

static bool myFunction(Node& p1, Node& p2) {}
priority_queue <Node, vector<Node>, function<bool(Node&, Node&)>> pq1(myFunction);

2

最初に比較を定義する必要があります。これを行うには3つの方法があります。

  1. クラスを使用する
  2. 構造体を使用する(クラスと同じ)
  3. ラムダ関数を使用します。

宣言するのは簡単なので、実行中のコードの上にこのコード行を書くだけなので、class / structを使用するのは簡単です。

struct compare{
  public:
  bool operator()(Node& a,Node& b) // overloading both operators 
  {
      return a.w < b.w: // if you want increasing order;(i.e increasing for minPQ)
      return a.w > b.w // if you want reverse of default order;(i.e decreasing for minPQ)
   }
};

呼び出しコード:

priority_queue<Node,vector<Node>,compare> pq;

0

構造体を好む、そしてそれはstd :: greatdo

struct Compare {
  bool operator()(Node const&, Node &) {}
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.