算法可以与表达式模板兼容吗?

Tem*_*Rex 5 c++ expression-templates range-v3

假设我有一些基于数组的代码可供表达式模板使用。例如,我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{});
Run Code Online (Sandbox Code Playgroud)

当然,我想能够短路计算和具有经修饰的(范围为基础的)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]
Run Code Online (Sandbox Code Playgroud)

就其输入lib::any_of而言写入operator[]将完成这项工作,就像为重载的operator+. 但是,这需要对我可能在此类数组上运行的所有 STL 算法进行类似的重新实现。

问题:所以假设我想通过仅修改ExprArray iterators. 是否可以修改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{});
Run Code Online (Sandbox Code Playgroud)

所以如果算法版本实际上是根据迭代器实现的,循环for (auto it = first; it != last; ++it)需要*it知道它需要计算的事实b[i] + c[i],并且++it必须知道它需要做的++i

Cas*_*sey 4

这个问题似乎简化为“我可以为我的表达式模板实现迭代器吗?” 我认为这相当简单。假设“表达式模板”知道它们的size并且已经重载了operator[]迭代器,只需保存对表达式对象的引用以及它所表示的范围的偏移量:

template <class Expr>
class iterator {
public:
  using iterator_category = ranges::random_access_iterator_tag;
  using difference_type = std::ptrdiff_t;
  using value_type = typename Expr::value_type;

  iterator() = default;
  constexpr iterator(Expr& e, difference_type i) :
    expr_{&e}, i_{i} {}

  constexpr bool operator==(const iterator& that) const {
    return assert(expr_ == that.expr_), i_ == that.i_;
  }
  constexpr bool operator!=(const iterator& that) const {
    return !(*this == that);
  }
  // Similarly for operators <, >, <=, >=

  value_type operator*() const {
    return (*expr_)[i_];
  }
  value_type operator[](difference_type n) const {
    return (*expr_)[i_ + n];

  iterator& operator++() & { ++i_; }
  iterator operator++(int) & { auto tmp = *this; ++*this; return tmp; }
  // Similarly for operator--

  iterator operator+(difference_type n) const {
    return iterator{expr_, i_ + n};
  }
  // Similarly for operators -, +=, and -=

  friend iterator operator+(difference_type n, const iterator& i) {
    return i + n;
  }

private:
    Expr* expr_;
    difference_type i_;
};
Run Code Online (Sandbox Code Playgroud)

现在您只需安排“表达式模板”以包含begin返回和end的成员。iterator{*this, 0}iterator{*this, size()}