#include <iostream>
#include <iterator>
#include <limits>
#include <vector>
template <typename T>
struct iterator_extractor { typedef typename T::iterator type; };
template <typename T>
struct iterator_extractor<T const> { typedef typename T::const_iterator type; };
template <typename T>
class Indexer {
public:
class iterator {
typedef typename iterator_extractor<T>::type inner_iterator;
typedef typename std::iterator_traits<inner_iterator>::reference inner_reference;
public:
typedef std::pair<size_t, inner_reference> reference;
iterator(inner_iterator it): _pos(0), _it(it) {}
reference operator*() const { return reference(_pos, *_it); }
iterator& operator++() { ++_pos; ++_it; return *this; }
iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
bool operator==(iterator const& it) const { return _it == it._it; }
bool operator!=(iterator const& it) const { return !(*this == it); }
private:
size_t _pos;
inner_iterator _it;
};
Indexer(T& t): _container(t) {}
iterator begin() const { return iterator(_container.begin()); }
iterator end() const { return iterator(_container.end()); }
private:
T& _container;
}; // class Indexer
template <typename T>
Indexer<T> index(T& t) { return Indexer<T>(t); }
int main() {
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9};
auto in = index(v);
for (auto it = in.begin(), end = in.end(); it != end; ++it) {
auto p = *it;
std::cout << p.first << ": " << p.second << "\n";
}
}
ICAgICNpbmNsdWRlIDxpb3N0cmVhbT4KICAgICNpbmNsdWRlIDxpdGVyYXRvcj4KICAgICNpbmNsdWRlIDxsaW1pdHM+CiAgICAjaW5jbHVkZSA8dmVjdG9yPgoKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIHN0cnVjdCBpdGVyYXRvcl9leHRyYWN0b3IgeyB0eXBlZGVmIHR5cGVuYW1lIFQ6Oml0ZXJhdG9yIHR5cGU7IH07CgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICBzdHJ1Y3QgaXRlcmF0b3JfZXh0cmFjdG9yPFQgY29uc3Q+IHsgdHlwZWRlZiB0eXBlbmFtZSBUOjpjb25zdF9pdGVyYXRvciB0eXBlOyB9OwoKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICAgIGNsYXNzIEluZGV4ZXIgewogICAgcHVibGljOgogICAgICAgIGNsYXNzIGl0ZXJhdG9yIHsKICAgICAgICAgICAgdHlwZWRlZiB0eXBlbmFtZSBpdGVyYXRvcl9leHRyYWN0b3I8VD46OnR5cGUgaW5uZXJfaXRlcmF0b3I7CgogICAgICAgICAgICB0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6aXRlcmF0b3JfdHJhaXRzPGlubmVyX2l0ZXJhdG9yPjo6cmVmZXJlbmNlIGlubmVyX3JlZmVyZW5jZTsKICAgICAgICBwdWJsaWM6CiAgICAgICAgICAgIHR5cGVkZWYgc3RkOjpwYWlyPHNpemVfdCwgaW5uZXJfcmVmZXJlbmNlPiByZWZlcmVuY2U7CgogICAgICAgICAgICBpdGVyYXRvcihpbm5lcl9pdGVyYXRvciBpdCk6IF9wb3MoMCksIF9pdChpdCkge30KCiAgICAgICAgICAgIHJlZmVyZW5jZSBvcGVyYXRvciooKSBjb25zdCB7IHJldHVybiByZWZlcmVuY2UoX3BvcywgKl9pdCk7IH0KCiAgICAgICAgICAgIGl0ZXJhdG9yJiBvcGVyYXRvcisrKCkgeyArK19wb3M7ICsrX2l0OyByZXR1cm4gKnRoaXM7IH0KICAgICAgICAgICAgaXRlcmF0b3Igb3BlcmF0b3IrKyhpbnQpIHsgaXRlcmF0b3IgdG1wKCp0aGlzKTsgKysqdGhpczsgcmV0dXJuIHRtcDsgfQoKICAgICAgICAgICAgYm9vbCBvcGVyYXRvcj09KGl0ZXJhdG9yIGNvbnN0JiBpdCkgY29uc3QgeyByZXR1cm4gX2l0ID09IGl0Ll9pdDsgfQogICAgICAgICAgICBib29sIG9wZXJhdG9yIT0oaXRlcmF0b3IgY29uc3QmIGl0KSBjb25zdCB7IHJldHVybiAhKCp0aGlzID09IGl0KTsgfQoKICAgICAgICBwcml2YXRlOgogICAgICAgICAgICBzaXplX3QgX3BvczsKICAgICAgICAgICAgaW5uZXJfaXRlcmF0b3IgX2l0OwogICAgICAgIH07CgogICAgICAgIEluZGV4ZXIoVCYgdCk6IF9jb250YWluZXIodCkge30KCiAgICAgICAgaXRlcmF0b3IgYmVnaW4oKSBjb25zdCB7IHJldHVybiBpdGVyYXRvcihfY29udGFpbmVyLmJlZ2luKCkpOyB9CiAgICAgICAgaXRlcmF0b3IgZW5kKCkgY29uc3QgeyByZXR1cm4gaXRlcmF0b3IoX2NvbnRhaW5lci5lbmQoKSk7IH0KCiAgICBwcml2YXRlOgogICAgICAgIFQmIF9jb250YWluZXI7CiAgICB9OyAvLyBjbGFzcyBJbmRleGVyCgogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgICBJbmRleGVyPFQ+IGluZGV4KFQmIHQpIHsgcmV0dXJuIEluZGV4ZXI8VD4odCk7IH0KCiAgICBpbnQgbWFpbigpIHsKICAgICAgICBzdGQ6OnZlY3RvcjxpbnQ+IHZ7MSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOX07CgogICAgICAgIGF1dG8gaW4gPSBpbmRleCh2KTsKCiAgICAgICAgZm9yIChhdXRvIGl0ID0gaW4uYmVnaW4oKSwgZW5kID0gaW4uZW5kKCk7IGl0ICE9IGVuZDsgKytpdCkgewogICAgICAgICAgICBhdXRvIHAgPSAqaXQ7CiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCBwLmZpcnN0IDw8ICI6ICIgPDwgcC5zZWNvbmQgPDwgIlxuIjsKICAgICAgICB9CiAgICB9