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)
最困难的问题是弄清楚代码中的返回类型。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)