在Boost :: range中编写适配器

bru*_*ery 11 c++ boost functional-programming boost-range

我开始玩Boost :: Range,以便在C++中使用延迟转换管道.我现在的问题是如何在较小的部分拆分管道.假设我有:

int main(){
  auto map = boost::adaptors::transformed; // shorten the name
  auto sink = generate(1) | map([](int x){ return 2*x; })
                          | map([](int x){ return x+1; })
                          | map([](int x){ return 3*x; });
  for(auto i : sink)
    std::cout << i << "\n";
}
Run Code Online (Sandbox Code Playgroud)

我想用a替换前两个地图magic_transform,即:

int main(){
  auto map = boost::adaptors::transformed; // shorten the name
  auto sink = generate(1) | magic_transform()
                          | map([](int x){ return 3*x; });
  for(auto i : sink)
    std::cout << i << "\n";
}
Run Code Online (Sandbox Code Playgroud)

怎么会写magic_transform?我查看了Boost :: Range的文档,但我无法很好地掌握它.

附录:我想写一个这样的课:

class magic_transform {
    ... run_pipeline(... input) {
        return input | map([](int x){ return 2*x; })
                     | map([](int x){ return x+1; });
};
Run Code Online (Sandbox Code Playgroud)

Jes*_*ood 5

最困难的问题是弄清楚代码中的返回类型。decltype和lambda混合不好(请参阅此处),因此我们必须考虑另一种方法:

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; });
Run Code Online (Sandbox Code Playgroud)

简单的解决方案是将lambda放入其中,std::function以便我们可以decltype推断出返回类型。我magic_transform在示例中使用了名称空间,但是如果您愿意的话,也可以将此代码改编为类。这是使您的代码适应上述要求的链接

另外,std::function在这里使用可能会过分杀伤。相反,您可以只声明两个常规函数(示例)。

我也在进行实验boost::any_range,似乎与C + 11 lambda不兼容,等等。我能得到的最接近的是以下示例示例):

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";
}
Run Code Online (Sandbox Code Playgroud)