c++boostc++11boost-range

boost transform iterator and c++11 lambda


I'm trying to use boost::adaptors::transformed by providing a c++0x lambda to the adaptor.

The following code does not compile. I'm using g++ 4.6.2 with 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;
}

Any ideas on what I'm doing wrong here?


Solution

  • Well lambdas don't play nice, since they are not default constructible, which is necessary for iterators. Here is a wrapper I use for 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);
    }
    

    Then you can just do this:

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