Ответ 1
Самая сложная проблема заключается в определении типа возврата в коде. decltype
и lambdas не смешиваются хорошо (см. здесь), поэтому мы должны думать об альтернативном способе:
auto map = boost::adaptors::transformed;
namespace magic_transform
{
std::function<int(int)> f1 = [](int x){ return 2*x; };
std::function<int(int)> f2 = [](int x){ return x+1; };
template <typename Range>
auto run_pipeline(Range input) -> decltype(input | map(f1) | map(f1))
{
return input | map(f1) | map(f2);
}
}
...
auto sink = magic_transform::run_pipeline(generate(1))
| map([](int x){ return 3*x; });
Простым решением является привязка lambdas к std::function
, поэтому мы можем использовать decltype
для вывода возвращаемого типа. Я использовал пространство имен magic_transform
в этом примере, но вы также можете адаптировать этот код к классу, если хотите. Вот ссылка, адаптирующая ваш код к указанному выше.
Кроме того, использование std::function
может быть излишним. Вместо этого вы можете просто объявить две нормальные функции (пример).
Я также экспериментировал с boost::any_range
, кажется, есть некоторые несовместимости с C + 11 lambdas и т.д. Ближайшим, что я мог получить, было следующее (пример):
auto map = boost::adaptors::transformed;
using range = boost::any_range<
const int,
boost::forward_traversal_tag,
const int&,
std::ptrdiff_t
>;
namespace magic_transform
{
template <typename Range>
range run_pipeline(Range r)
{
return r | map(std::function<int(int)>([](int x){ return 2*x; }))
| map(std::function<int(int)>([](int x){ return x+1; }));
}
}
int main(){
auto sink = magic_transform::run_pipeline(boost::irange(0, 10))
| map([](int x){ return 3*x; });
for(auto i : sink)
std::cout << i << "\n";
}