Assuming you'd accept that your loop is slightly changed, it is certainly doable:
for (auto item : myIterationClass(vector_var)) {
item.index();
item.value();
item.erase();
item.replaceWith(42);
}
The idea is to have myIterationClass()
be a thin wrapper which return iterators with a fairly custom value. The use of erase()
is a bit problematic, though, as you are not supposed to change the container while it is being iterated, i.e., if these are really needed it is necessary to record the elements to be erased and process them later.
Although I don't this this is a good idea, below is a quick demo implementing index()
and value()
. Implementing replaceWith()
would be trivial while implementing anything mutating the length of the sequence could be interesting. Given that the iterator controls the sequence it could probably be done by directly mutating the underlying sequence and adjusting the kept index appropriately. Note that there are also different approach how the iterators are represented. I randomly choose to use a combination of a pointer to the container and an index. If the sequence doesn't add or remove elements, it could also be done using two iterator and computing the index as the difference between the two.
#include <algorithm>
#include <iostream>
#include <vector>
template <typename T>
class wrapped_iterator
{
T* container;
typename T::size_type position;
public:
wrapped_iterator(T* container, typename T::size_type position)
: container(container)
, position(position) {
}
wrapped_iterator<T>& operator*() { return *this; }
wrapped_iterator<T>& operator++() { ++position; return *this; }
wrapped_iterator<T> operator++(int) {
wrapped_iterator<T> rc(*this);
++*this;
return rc;
}
bool operator== (wrapped_iterator<T> const& other) const {
return position == other.position;
}
bool operator!= (wrapped_iterator<T> const& other) const {
return !(*this == other);
}
typename T::size_type index() const { return position; }
typename T::const_reference& value() const { return (*container)[position]; }
};
template <typename T>
class wrapped
{
T* container;
public:
typedef wrapped_iterator<T> iterator;
wrapped(T& container): container(&container) {}
iterator begin() const { return iterator(container, 0u); }
iterator end() const { return iterator(container, container->size()); }
};
template <typename T>
wrapped<T> wrapper(T& container) {
return wrapped<T>(container);
}
int main()
{
std::vector<int> v{ 7, 6, 5, 4, 3, 2, 1 };
for (auto item : wrapper(v)) {
std::cout << "index=" << item.index() << ' '
<< "value=" << item.value() << '\n';
}
}