2012-10-01 22 views
12

Estoy tratando de usar boost :: adapters :: transform proporcionando un C++ 0x lambda al adaptador.boost transform iterator y C++ 11 lambda

El siguiente código no se compila. Estoy usando g ++ 4.6.2 con boost 1.48.

#include <iostream> 
#include <vector> 

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

using namespace std; 
namespace br = boost::range; 
namespace badpt = boost::adaptors; 


int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    auto my_ftor = [&b](int r)->int{return b[r];}; 

    cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl; 
} 

¿Alguna idea sobre qué estoy haciendo mal aquí?

+0

¿Qué error obtiene? – ronag

+0

http://stackoverflow.com/questions/12672372/boost-transform-iterator-and-c11-lambda relacionado y mb dup. – ForEveR

+0

El registro de errores es detallado. Ver [enlace] (http://pastebin.com/grsENb1m). – Nithin

Respuesta

4

Las lambdas buenas no funcionan bien, ya que no son predecibles, lo cual es necesario para los iteradores. Aquí es una envoltura que utilizo para lambdas:

#define RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } 

template<class Fun> 
struct function_object 
{ 
    boost::optional<Fun> f; 

    function_object() 
    {} 
    function_object(Fun f): f(f) 
    {} 

    function_object(const function_object & rhs) : f(rhs.f) 
    {} 

    // Assignment operator is just a copy construction, which does not provide 
    // the strong exception guarantee. 
    function_object& operator=(const function_object& rhs) 
    { 
     if (this != &rhs) 
     { 
      this->~function_object(); 
      new (this) function_object(rhs); 
     } 
     return *this; 
    } 

    template<class F> 
    struct result 
    {}; 

    template<class F, class T> 
    struct result<F(T)> 
    { 
     typedef decltype(std::declval<Fun>()(std::declval<T>())) type; 
    }; 

    template<class T> 
    auto operator()(T && x) const RETURNS((*f)(std::forward<T>(x))) 

    template<class T> 
    auto operator()(T && x) RETURNS((*f)(std::forward<T>(x))) 
}; 

template<class F> 
function_object<F> make_function_object(F f) 
{ 
    return function_object<F>(f); 
} 

A continuación, sólo se puede hacer esto:

int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    cout<<*br::max_element(a|badpt::transformed(make_function_object([&b](int r)->int{return b[r];};)))<<endl; 
} 
8

Es un problema bien conocido. Mira

http://boost.2283326.n4.nabble.com/range-cannot-use-lambda-predicate-in-adaptor-with-certain-algorithms-td3560157.html

Poco, se debe utilizar esta macro

#define BOOST_RESULT_OF_USE_DECLTYPE 

para su uso en lugar de decltypeboost::result_of.

Presupuesto de here

Si su compilador soporta decltype, a continuación, se puede activar tipo de deducción automática resultado mediante la definición de la macro BOOST_RESULT_OF_USE_DECLTYPE, como en el siguiente ejemplo.

+1

Hola, según tengo entendido, esto es aplicable para impulsar 1.51 +. Intenté insertar la macro antes de incluir encabezados de impulso, pero no tiene ningún efecto. Las otras soluciones en el enlace también suponen la disponibilidad de boost/range/regular.hpp que no está disponible en boost-1.48. Gracias por el enlace. – Nithin

+1

@Nithin esta macro corrige más errores, pero hay errores que no pueden corregirse sin boost :: range rewriting (por ejemplo, funto de construcción por defecto c-tor (versión de impulso 1.48) nunca funcionará con cierre). No use cierres con boost :: transform_iterator ahora – ForEveR

+0

¡Oh bien! Gracias por el aporte. Probablemente vaya con la sugerencia de @Paul ya que realmente no puedo cambiar la versión de refuerzo ahora. – Nithin

1

@ respuesta de siempre (#define BOOST_RESULT_OF_USE_DECLTYPE) no funcionó para mí. Y la respuesta de @ Paul es demasiado larga (y demasiado general). Una solución más específica puede ser la siguiente:

#include <iostream> 
#include <vector> 

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

using namespace std; 
namespace br = boost::range; 
namespace badpt = boost::adaptors; 


int main() 
{ 
    vector<int> a = {0,3,1,}; 
    vector<int> b = {100,200,300,400}; 

    struct{ 
    vector<int>* bP;        //pointer, just to imitate lambda syntax... 
    int operator()(int r) const{return (*bP)[r];} //was my_ftor = [&b](int r)->int{return b[r];}; 
    } my_ftor{&b};         //...here 

    cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl; 
} 

(Es 2016, Boost 1.58 y esto todavía está roto Al menos lambda sin capturas debe cumplir con los requisitos de boost::transformed..)

Si la lambda didn no tiene una captura (no es su caso) el código sería un poco más simple O podría usar:

... 
int(*my_ftor)(int) = [](int r)->int{return ...;}; // function pointer default constructible and callable 
cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl; 
...