web-dev-qa-db-ja.com

ラムダコンパレータエラーのあるC ++ priority_queue

VC2010でコンパイルしようとしている次のエラーコードがありますが、エラーが発生します C2974 これはラムダ式を含めた場合にのみ発生するため、何かする必要があると思いますそれと。

typedef pair<pair<int, int>, int> adjlist_Edge;
priority_queue< adjlist_Edge , vector<adjlist_Edge>,
    [](adjlist_Edge a, adjlist_Edge b) -> bool {
        if(a.second > b.second){ return true; } else { return false; }
    }> adjlist_pq;

テンプレート定義の形式が正しいことを知っています

priority_queue<int , vector<int>, greater<int>> pq;

期待どおりに動作します。私が間違っているアイデアはありますか?私が見落としているかもしれない、間違って見えるラムダに明らかに何か悪いことはありますか?読んでくれてありがとう!

43
ameer

最初にラムダオブジェクトを定義してから、decltypeを使用してテンプレートの型に渡し、コンストラクタに直接渡します。

auto comp = []( adjist a, adjlist b ) { return a.second > b.second; };
priority_queue< adjlist_Edge , vector<adjlist_Edge>, decltype( comp ) >
     adjlist_pq( comp );
65
Potatoswatter

priority_queueは、コンパレーターをテンプレート引数として受け取ります。ラムダ関数はオブジェクトであるため、テンプレート引数として使用することはできません(整数型のなかで使用できる型はごくわずかです)。

そこでdecltypeを使ってみることができます:

priority_queue< adjlist_Edge , vector<adjlist_Edge>,
               decltype( [](adjlist_Edge a, adjlist_Edge b) -> bool {
                if(a.second > b.second){ return true; } else { return false; }
               })>
adjlist_pq( [](adjlist_Edge a, adjlist_Edge b) -> bool {
                if(a.second > b.second){ return true; } else { return false; }
             } );

それが失敗した場合(そうなるでしょう)、function<>を使用できます。

priority_queue< adjlist_Edge , vector<adjlist_Edge>,
                function<bool(adjlist_Edge,adjlist_Edge)> >
adjlist_pq( [](adjlist_Edge a, adjlist_Edge b) -> bool {
                if(a.second > b.second){ return true; } else { return false; }
            } );
16

受け入れられた回答はhowと答え、カスタム比較オブジェクトとしてラムダ式を使用してpriority_queueを定義しています。私は質問の別の側面に対処します:whyあなたの方法でpqを定義すると失敗します:

typedef pair<pair<int, int>, int> adjlist_Edge;
priority_queue< adjlist_Edge , vector<adjlist_Edge>,
    [](adjlist_Edge a, adjlist_Edge b) -> bool {
        if(a.second > b.second){ return true; } else { return false; }}> adjlist_pq;

なぜ優先キューを作成するときにラムダをパラメーターとして渡さなければならないのですか?その理由はラムダ式にはデフォルトのコンストラクターがないにあります。そのため、優先度キューを作成するときに指定しない場合、ラムダ式の「想定される既存のデフォルトコンストラクター」が呼び出されます。明らかに、それは失敗するでしょう。

あなたの質問に関して:それはCompareオブジェクト(ラムダまたは関数オブジェクト)がデフォルトのコンストラクタを持つかどうかが違いを生むことです。

0
kz28