开发者

Flexible mutation of sequence containers in C++

开发者 https://www.devze.com 2023-01-04 15:55 出处:网络
I\'m pondering a current limitation of STL iterators and wondering if there\'s an elegant way around it. Here\'s my situation: I have a class that encapsulates a sequence container and a generic metho

I'm pondering a current limitation of STL iterators and wondering if there's an elegant way around it. Here's my situation: I have a class that encapsulates a sequence container and a generic method to mutate the contents of the container, for example:

class Container {
  typedef std::vector<int> Data;
  Data data_;
 public:
  template <class Mutator>
  ?? mutate() {
    Mutator m;
    return m(??);
  }
};

Some details have been elided for concision, but the main problem I'm considering is what to pass to the mutator (the ?? in the m() functor call). A secondary question is what to return from mutate to allow simple composition of mutators. One possibility is to pass (and return) a begin/end pair of iterators into data_, or even a boost::sub_range, for example:

template <class Mutator>
boost::sub_range<Data> mutate() {
  Mutator m;
  return m(boost::sub_range<Data>(data_);
}

This would allow me to do most of what I want on the data, such as negating all values in range, multiplying by a factor, etc. This also allows me chain, or compose, various mutators, as in this (shortened) version:

return m1(m2(m3(data_)));

Thus, any mutator can, for example, pick a subrange of its input to limit the range that the outer mutators work on, a desirable feature. And all these mutators can c开发者_运维知识库hange data in-place, which is nicely efficient.

What this syntax cannot do, however, is to modify the size of the container (at least not with vector), so mutators that insert or remove elements can't work with an iterator-based interface. An alternative interface passes the entire container to the mutator. I'm not sure how to deal with subranging in that case, and it also feels like a less elegant solution than the generic and minimal-requirements iterator-based solution.

I would appreciate any ideas on how to deal with this limitation.


You can combine functors (Think: Function Composition) with boost::bind.

On the other hand I feel I don't fully understand: is the second functor supposed to work on a different range than the first functor? Is data going to be removed from the container?

Be aware: You current solution has non obvious costs: every composition of "mutators" would require a new iteration instead of being "real composition of mutators".

0

精彩评论

暂无评论...
验证码 换一张
取 消