C++ 在Boost::range中组合适配器
我开始玩Boost::Range以获得更好的性能。我现在的问题是如何将管道分成更小的部分。假设我有:C++ 在Boost::range中组合适配器,c++,boost,functional-programming,boost-range,C++,Boost,Functional Programming,Boost Range,我开始玩Boost::Range以获得更好的性能。我现在的问题是如何将管道分成更小的部分。假设我有: 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; })
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";
}
如何编写magic_transform
?我抬头看了看,但是我不能很好地理解它
附录:我想写一个这样的课程:
class magic_transform {
... run_pipeline(... input) {
return input | map([](int x){ return 2*x; })
| map([](int x){ return x+1; });
};
我认为这会起作用:
auto magic_transform()->decltype(boost::adaptors::transformed(std::function<int(int)>())
{
std::function<int(int)> retval = [](int x){ return [](int x){ return x+1; }(2*x);
return boost::adaptors::transformed(retval);
}
auto magic_transform()->decltype(boost::adapters::transformed(std::function())
{
函数retval=[](intx){return[](intx){return x+1;}(2*x);
返回boost::adapters::transformed(retval);
}
但它可能不是您想要的。:(上面代码中的笑话:2*x+1的链式lambda,基本上在实现中使用decltype来查找返回类型)
查看http://www.boost.org/doc/libs/1_46_1/boost/range/adaptor/transformed.hpp
,magic\u transform
想要返回的类型是boost::range\u detail::transform\u holder
,其中T是函数的类型
当您使用lambdas在堆栈上执行此操作时,T
最终会成为一些非常狭窄的类型。如果您希望在不公开所有细节的情况下传递抽象转换,那么使用std::function
可能是合理的(将有少量的运行时开销)
希望能奏效。最困难的问题是找出代码中的返回类型。
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; });
generate
的返回类型是什么?我担心您的sink
包含对在分号处过期的临时变量的引用。generate
的返回类型是boost::iterator\u range
,请查看详细信息。Magic transform没有获得输入参数。您将其作为空函数编写。好的,是吗更像是一个类而不是一个函数。见上文。你的需求仍然模糊。这是你想要的管道语法吗?围绕链接lamdas的转换提供了|的功能和外部使用。你真的想要|在你的magic|u转换中,如果是,为什么?是的,链接lambdas不是我想要的:),请检查我的更新。我可以ld实际上使用了auto
和decltype
,但我想要更通用的东西。所以您需要某种管道方式(按顺序组合)一起转换并使结果成为一个转换?不仅转换,而且最终过滤和其他范围适配器。范围适配器的结果类型被记录。例如,transformed
返回boost::transformed\u range在这里询问之前,我尝试了decltype
,发现它对于这个应用程序来说太冗长了(你最后写了两次管道。)any_range
,oth,只允许你指定输入和输出,对吗?现在我明白了,any_range
指定了输出(值和引用)。很有趣。另外,你也可以对参数使用any_range
。例如:range run_管道(range r)
定义了一个作用于一个整数范围并返回一个整数范围的管道。@brunonery:是的,我无法使任何\u范围
用于您的生成(1)
示例。@brunonery:我发现您需要将迭代器标记更改为std::forward\u迭代器\u标记
。
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; });
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";
}