C++迭代器流水线设计
假设我们要应用一系列转换,int f1(int)
、int f2(int)
、int f3(int)
,对象列表。一种天真的方法是,
SourceContainer source;
TempContainer1 temp1;
transform(source.begin(), source.end(), back_inserter(temp1), f1);
TempContainer2 temp2;
transform(temp1.begin(), temp1.end(), back_inserter(temp2), f2);
TargetContainer target;
transform(temp2.begin(), temp2.end(), back_inserter(target), f3);
由于 temp1
和 temp2
需要额外的空间,因此这个第一个解决方案并不是最佳的。因此,让我们变得更聪明:
int f123(int n) { return f3(f2(f1(n))); }
...
SourceContainer source;
TargetContainer target;
transform(source.begin(), source.end(), back_inserter(target), f123);
这个第二解决方案要好得多,因为不仅代码更简单,而且更重要的是,没有中间计算,空间需求更少。
但是,组合 f123
必须在编译时确定,因此在运行时固定。
如果要在运行时确定组合,我将如何有效地做到这一点?例如,如果此代码位于 RPC 服务中,并且实际组合可以是 f1
、f2
和 f3< 的任何子集的任意排列/code>--基于 RPC 调用的参数。
Suppose we want to apply a series of transformations, int f1(int)
, int f2(int)
, int f3(int)
, to a list of objects. A naive way would be
SourceContainer source;
TempContainer1 temp1;
transform(source.begin(), source.end(), back_inserter(temp1), f1);
TempContainer2 temp2;
transform(temp1.begin(), temp1.end(), back_inserter(temp2), f2);
TargetContainer target;
transform(temp2.begin(), temp2.end(), back_inserter(target), f3);
This first solution is not optimal because of the extra space requirement with temp1
and temp2
. So, let's get smarter with this:
int f123(int n) { return f3(f2(f1(n))); }
...
SourceContainer source;
TargetContainer target;
transform(source.begin(), source.end(), back_inserter(target), f123);
This second solution is much better because not only the code is simpler but more importantly there is less space requirement without the intermediate calculations.
However, the composition f123
must be determined at compile time and thus is fixed at run time.
How would I try to do this efficiently if the composition is to be determined at run time? For example, if this code was in a RPC service and the actual composition--which can be any permutation of any subset of f1
, f2
, and f3
--is based on arguments from the RPC call.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
编辑:工作版本位于 http://ideone.com/5GxnW 。下面的版本有想法但无法编译。它支持运行时类型检查和运行时函数组合。
这个想法是定义一个通用(一元)函数类,以及一种通过运行时类型检查来组合它们的方法。这是通过结合
boost::any
、boost::function
和类型擦除习惯用法来完成的。现在,让我们使用标准算法来执行此操作(这甚至适用于空序列):
并使用以下内容来应用它
您甚至可以使用
boost::transform_iterator
EDIT: Working version at http://ideone.com/5GxnW . The version below has the ideas but does not compile. It supports run time type checking, and run time function composition.
The idea is to define a generic (unary) function class, and a way to compose them with run time type checks. This is done with a combination of
boost::any
,boost::function
and the type erasure idiom.Now, let's use standard algorithms and do this (this even works on empty sequences):
and use the following to apply it
You can even use
boost::transform_iterator
对于 C++0x,我们应该能够使用
auto
来消除指定参数/返回类型的麻烦。目前我假设它们是相同的,但从理论上讲,您可能希望能够在组合中包含转换。With C++0x, we should be able to use
auto
to eliminate having to specify the argument/return type. For the moment I've assumed they're the same, though in theory, you might like the ability to include conversions in the mix.您应该使用仿函数而不是函数,并将所需的变换函数传递到仿函数的构造函数中,
例如
如果您需要可变数量的函数,则更改仿函数构造函数签名以使用函数向量并在调用变换之前填充该向量。
you should use a functor instead of function and pass needed transform functions into functor's constructor
something like
if you need variable number of functions then change
Functor
constructor signature to use vector of functions and fill that vector before calling transform.Just定义一个迭代器来执行您想要的操作:Justdefine an iterator that does what you want: