【发布时间】:2015-11-25 10:09:38
【问题描述】:
假设我有一些基于数组的代码可以被表达式模板使用。例如,我为这些数组重载了 operator[],并且还重载了算术运算符 + 等。
现在我想让 STL 算法any_of 在这样的数组上运行。简单的方法就是这样做
ExprArray<double, N> b, c; // init etc.
auto a = b + c; // for (auto i = 0; i < N; ++i) { a[i] = b[i] + c[i]; }
auto res = std::any_of(begin(a), end(a), SomePred{});
当然,我希望能够缩短计算并有一个经过修改的(基于范围的)lib::any_of
// only compute b[i] + c[i] until SomePred is satisified
auto res = lib::any_of(b + c, SomePred{}); // write as explicit loop over b[i] + c[i]
在其输入上以operator[] 形式写入lib::any_of 将完成这项工作,就像对重载的operator+ 所做的一样。但是,这需要对我可能在此类数组上运行的所有 STL 算法进行类似的重新实现。
问题:假设我想通过仅修改 ExprArray iterators 来重用现有的基于范围的算法(Boost.Range、range-v3)。是否可以修改 ExprArray 迭代器 operator* 和 operator++,使其对基于范围的算法透明?
// only compute b[i] + c[i] until SomePred is satisified
// needs to eventually dispatch to
// for (auto i = 0; i < N; ++i)
// if (SomePred(b[i] + c[i])) return true;
// return false;
auto res = ranges::any_of(b + c, SomePred{});
所以如果算法版本实际上是根据迭代器实现的,循环for (auto it = first; it != last; ++it) 需要*it 知道它需要计算b[i] + c[i] 的事实,而++it 必须知道它需要做++i.
【问题讨论】:
-
当谓词为真时停止对于
std::any_of来说应该是一件很自然的事情,您是否检查过它是否已经这样做了? (你可以通过传递一个打印它作为谓词接收的值的 lambda 来做到这一点。) -
@JoachimPileborg 停止并不是真正的问题,它是表达式模板及其开始/结束迭代器的惰性计算。如果我只重载了
operator[],我需要一个基于迭代器的实现来了解它接收表达式模板并将*it转换为适当的expr[i]的事实。问题是,迭代器的operator*可以为我做那种工作吗? -
@TemplateRex 请注意,问题是关于算法 c++ 库而不是算法设计,所以算法标签不合适
-
既然你是编写迭代器类的人(我假设),你可以让它做任何你需要的事情。
-
@TemplateRex 不是算法的实现,而是迭代器类别的要求,我想说。也就是说,根据类别,迭代器上允许使用哪些表达式。
标签: c++ expression-templates range-v3