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 change 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.