web-dev-qa-db-fra.com

C ++ priority_queue avec erreur du comparateur lambda

J'ai le code erroné suivant que j'essaye de compiler dans VC2010, mais j'obtiens l'erreur C2974 cela ne se produit que lorsque j'inclus l'expression lambda, donc je suppose que cela a quelque chose à faire avec ça.

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;

Je sais que la forme de la définition du modèle est correcte car

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

Fonctionne comme prévu. Des idées sur ce que je fais mal? Y a-t-il manifestement quelque chose qui ne va pas avec la lambda qui semble mal que je pourrais négliger? Merci d'avoir lu!

43
ameer

Définissez d'abord l'objet lambda, puis passez-le au type de modèle à l'aide de decltype et passez-le également directement au constructeur.

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 prend le comparateur comme argument de modèle. Les fonctions lambda sont des objets, et ne peuvent donc pas être utilisées comme arguments de modèle (seuls quelques types peuvent l'être, parmi eux des types intégraux).

Vous pouvez essayer d'utiliser decltype ici:

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; }
             } );

A défaut (et ce sera), vous pouvez utiliser 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
Marc Mutz - mmutz

La réponse acceptée a répondu comment pour définir une priorité_queue avec une expression lambda en tant qu'objet de comparaison personnalisé. Je voudrais aborder un autre aspect de la question: pourquoi il échoue lors de la définition d'un pq à votre manière:

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;

Pourquoi devons-nous passer le lambda comme paramètre lors de la construction de la file d'attente prioritaire? La raison en est que l'expression lambda n'a pas de constructeur par défaut. Donc, si vous ne le fournissez pas lors de la construction de la file d'attente prioritaire, le "constructeur par défaut supposé existant" de l'expression lambda sera appelé. De toute évidence, cela échouerait.

En ce qui concerne votre question: c'est si l'objet Compare (lambda ou objet fonction) a un constructeur par défaut qui fait la différence.

0
kz28