2011-04-27 7 views
29

Tengo el siguiente código erróneo que estoy tratando de compilar en VC2010, pero me sale el error C2974 esto solo ocurre cuando incluyo la expresión lambda, entonces supongo que tiene algo para hacer con eso.C++ priority_queue con lambda comparator error

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; 

sé la forma de la definición de plantilla es correcta

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

funciona como se espera. ¿Alguna idea de lo que estoy haciendo mal? ¿Hay algo obviamente mal con la lambda que se ve mal que podría estar pasando por alto? ¡Gracias por leer!

+0

duplicado potencial de http://stackoverflow.com/questions/3867276/can-the-type-of-a-lambda-expression-be-expressed –

Respuesta

46

En primer lugar definir el objeto de lambda, y luego pasarlo a el tipo de plantilla usando decltype y también la pasa directamente al constructor.

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

Gracias, eso funciona si tengo que declararlo por separado ¿crees que hay algún beneficio de usar un objeto lambda sobre un functor? – ameer

+0

Re: constructor por defecto: [expr.prim.lambda]/19 dice que los operadores predeterminados de constuctor y asignación de copia se eliminan, y el constructor de copia y el destructor están implícitamente definidos, para cierres. –

+0

@mmutz: ¡Gracias, editado! – Potatoswatter

13

priority_queue toma el comparador como un argumento de plantilla. Las funciones de Lambda son objetos y, por lo tanto, no pueden utilizarse como argumentos de plantilla (solo pueden existir muy pocos tipos, entre ellos los tipos integrales).

Usted puede intentar usar decltype allí:

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

De no ser así (y va a), puede utilizar 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; } 
      }); 
+0

1 por estar más cerca de lo interjay, pero esto todavía no funciona porque cada función lambda tiene un tipo único, incluso dos objetos con definiciones idénticas. La función – Potatoswatter

+0

es mucho mejor, ya que no duplica el código (y aparentemente, es la única cosa correcta que se puede hacer). –

+0

@Alexandre: hay otra alternativa, que sacrifica ser un trazador de líneas, pero por lo demás es más limpio que 'función '. – Potatoswatter