I came up with a solution — or rather an experimental solution. Here is how you will end up using it:
for(auto item : make_indexable(v))
{
//std::get<0>(item) is the index
//std::get<1>(item) is the object
}
And here goes the minimal implementation (it is just to demonstrate the basic idea):
#include <tuple>
#include <functional>
template<typename C>
struct indexed_container
{
struct indexed_iterator
{
typedef typename C::value_type value_type;
typedef std::tuple<size_t, std::reference_wrapper<value_type>> tuple_type;
typename C::iterator _it;
size_t _index;
indexed_iterator(typename C::iterator it) : _it(it), _index(0) {}
indexed_iterator& operator++()
{
++_it;
++_index;
return *this;
}
bool operator == (indexed_iterator const & other)
{
return _it == other._it;
}
bool operator != (indexed_iterator const & other)
{
return _it != other._it;
}
tuple_type operator*()
{
return std::make_tuple(_index, std::ref(*_it));
}
};
indexed_container(C & c) : _c(c) {}
indexed_iterator begin()
{
return indexed_iterator(_c.begin());
}
indexed_iterator end()
{
return indexed_iterator(_c.end());
}
private:
C & _c;
};
template<typename C>
auto make_indexable(C & c) -> indexed_container<C>
{
return indexed_container<C>(c);
}
Test code:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1,2,3};
for(auto item : make_indexable(v))
{
std::cout << std::get<0>(item) << " => " << std::get<1>(item) << std::endl;
std::get<1>(item) *= 10; //modify value!
}
std::cout << "\nModified\n";
for(auto item : make_indexable(v))
{
std::cout << std::get<0>(item) << " => " << std::get<1>(item) << std::endl;
}
}
Output:
0 => 1
1 => 2
2 => 3
Modified
0 => 10
1 => 20
2 => 30
Online demo
Note that this solution is not perfect, as it will not work with temporaries and const containers (and containers of const objects). Also, right now the underlying object will be returned as reference even if you write auto item as opposed to auto & item (in fact, you cannot write auto &item). But I think these issues can be fixed with a bit more effort and careful design. After all, it is just a demonstration of the basic idea.
forloop.