итератор повышения трансформации и лямбда с ++ 11

Я пытаюсь использовать boost :: adapters :: преобразуется путем предоставления C ++ 0x лямбда для адаптера.

Следующий код не компилируется. Я использую g ++ 4.6.2 с надстройкой 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;
}

Любые идеи о том, что я делаю здесь не так?

12

Решение

Ну, лямбды не играют хорошо, так как они не являются конструктивными по умолчанию, что необходимо для итераторов. Вот обертка, которую я использую для лямбд:

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

Тогда вы можете просто сделать это:

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

Другие решения

Это хорошо известная проблема. Смотри сюда

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

Короче, вы должны использовать этот макрос

#define BOOST_RESULT_OF_USE_DECLTYPE

для использования decltype вместо boost::result_of,

Цитата из Вот

Если ваш компилятор поддерживает decltype, вы можете включить автоматический
вычет типа результата путем определения макроса
BOOST_RESULT_OF_USE_DECLTYPE, как в следующем примере.

8

@ ForEver’s answer (#define BOOST_RESULT_OF_USE_DECLTYPE) не работал для меня.
И ответ @ Paul слишком длинный (и слишком общий).
Более конкретное решение может быть таким:

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

(Это 2016, Boost 1.58, и он все еще не работает. По крайней мере, лямбда без захвата должна соответствовать требованиям boost::transformed.)

Если бы лямбда не имела перехвата (не ваш случай), код был бы немного проще ИЛИ вы могли бы использовать:

...
int(*my_ftor)(int) = [](int r)->int{return ...;}; // function pointer default constructible and callable
cout<<*br::max_element(a|badpt::transformed(my_ftor))<<endl;
...
1
По вопросам рекламы [email protected]