2012-10-01 8 views
12

Sto provando ad usare boost :: adapters :: trasformato fornendo un lambda C++ 0x all'adattatore.boost trasformatore iteratore e C++ 11 lambda

Il seguente codice non viene compilato. Sto 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; 
} 

Qualche idea su cosa sto facendo male qui?

+0

Che errore ottieni? – ronag

+0

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

+0

Il registro degli errori è dettagliato. Si prega di consultare [collegamento] (http://pastebin.com/grsENb1m). – Nithin

risposta

4

Bene i lambda non suonano bene, poiché non sono costruttibili di default, che è necessario per gli iteratori. Qui è un wrapper che uso per lambda:

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

allora si può solo fare questo:

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

È un problema ben noto. Guardate qui

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

Poco, si consiglia di utilizzare questa macro

#define BOOST_RESULT_OF_USE_DECLTYPE 

per l'uso decltype invece di boost::result_of.

Citazione di here

Se il compilatore supporta decltype, allora è possibile attivare automatico del tipo di risultato netto definendo la macro BOOST_RESULT_OF_USE_DECLTYPE, come nel seguente esempio.

+1

Ciao, come ho capito, questo è applicabile per aumentare 1,51 +. Ho provato ad inserire la macro prima di includere eventuali header di boost ma non ha alcun effetto. Le altre soluzioni nel link presuppongono anche la disponibilità di boost/range/regular.hpp che non è disponibile in boost-1.48. Grazie per il link. – Nithin

+1

@Non in questa macro correggi più errori, ma ci sono errori, che non possono essere risolti senza boost :: range rewriting (costrutto functor di default c-tor (boost versione 1.48) per esempio non funzionerà mai con la chiusura). Non usare chiusure con boost :: transform_iterator ora – ForEveR

+0

Oh bene! Grazie per l'input. Probabilmente andrò con il suggerimento di @Paul dato che non posso davvero cambiare la versione boost adesso. – Nithin

1

@ risposta di sempre (#define BOOST_RESULT_OF_USE_DECLTYPE) non ha funzionato per me. E la risposta di @ Paul è troppo lunga (e troppo generica). Una soluzione più specifico può essere questo:

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

(E 'il 2016, Boost 1.58 e questo è ancora rotto Almeno lambda senza cattura deve soddisfare i requisiti della boost::transformed..)

Se il lambda didn Se hai una cattura (non il tuo caso) il codice sarebbe un po 'più semplice OPPURE potresti usare:

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