2012-08-08 8 views
17

yo tratamos de compilar este código:uso de adaptadores de Boost con C++ 11 lambdas

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <vector> 

int main() { 
    std::vector<int> v{ 
     1,5,4,2,8,5,3,7,9 
    }; 
    std::cout << *boost::min_element(v | boost::adaptors::transformed(
      [](int i) { return -i; })) << std::endl; 
    return 0; 
} 

La compilación falló con el siguiente mensaje de error (después de una novela de instancias de molde largo):

/usr/local/include/boost/iterator/transform_iterator.hpp:84:26: error: use of deleted function ‘main()::<lambda(int)>::<lambda>()’ 
../main.cpp:12:5: error: a lambda closure type has a deleted default constructor 

Busqué en Google el problema y encontré this en el archivo de la lista de correo de los usuarios de Boost. Sugirió que usar #define BOOST_RESULT_OF_USE_DECLTYPE resolvería el problema. Lo puse al principio de mi código, pero todavía no compila. La longitud del mensaje de error parece ser mucho más corta, pero el mensaje de error al final es el mismo. Actualmente estoy usando Boost 1.50.

¿Cuál puede ser el problema aquí? ¿Hay alguna manera de hacer funcionar esto?

+0

Creo que necesita 1.51. Al menos eso es lo que lo hizo funcionar para mí. – Gurgeh

Respuesta

8

http://smellegantcode.wordpress.com/2011/10/31/linq-to-c-or-something-much-better/

Pero usted puede usar esto, que funciona bien.

#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 
#include <vector> 
#include <functional> 

int main() { 
    std::vector<int> v{ 
     1,5,4,2,8,5,3,7,9 
    }; 
    std::function<int(int)> func = [](int i) { return -i; }; 
    std::cout << *boost::min_element(v | boost::adaptors::transformed(
    func)) << std::endl; 
    return 0; 
} 

http://liveworkspace.org/code/b78b3f7d05049515ac207e0c12054c70

#define BOOST_RESULT_OF_USE_DECLTYPE funciona bien en VS2012 por ejemplo.

6

Esto se cubre en http://boost.2283326.n4.nabble.com/range-cannot-use-lambda-predicate-in-adaptor-with-certain-algorithms-td3560157.html y https://svn.boost.org/trac/boost/ticket/4189 - el problema es que algunos algoritmos esperan ser capaces de copiar-construcción (y por defecto-construcción, y copia-asignar) su predicado, el cual no se puede hacer con una lambda.

La solución consiste en envolver el lambda en un std::function:

*boost::min_element(
    v | boost::adaptors::transformed(std::function<int(int)>(
     [](int i) { return -i; }))); 

le he pedido (al Inferring the call signature of a lambda or arbitrary callable for "make_function") una manera de escribir una make_function de tal manera que uno puede escribir:

*boost::min_element(
    v | boost::adaptors::transformed(make_function(
     [](int i) { return -i; }))); 
9

Puede convertir una lambda no capturable en un puntero de función colocando un "+" delante de ella.

std::vector<int> v{1,5,4,2,8,5,3,7,9}; 
std::cout << *boost::min_element(v | 
    boost::adaptors::transformed(+[](int i) 
    { 
     return -i; 
    })) << std::endl; 
+0

¡esto funcionó para mí! –