Joshua Moerman (@Kassalade)
14 years ago
2 changed files with 118 additions and 0 deletions
@ -0,0 +1,97 @@ |
|||
/*
|
|||
|
|||
USAGE: |
|||
"for(auto x : counted(v)) { ... x.value ... x.index ... }" |
|||
x.value is a reference to the element in the container (so you can change it's value), x.index is what it is. |
|||
Container should havae forward iterators. |
|||
|
|||
NOTE: |
|||
This headers is purely a handy tool for the "for(auto x : counter(v))"-syntax. Using it explicitly with iterators is not recommended! |
|||
|
|||
NOTE: |
|||
There is no const version of it. Doing "for(const auto x : counted(v))" doesn't make it impossible to change x (so the element in the container can be modified). |
|||
|
|||
*/ |
|||
#include <iterator> |
|||
|
|||
// A reference is a struct, yuk...
|
|||
// Maybe a proxy is better
|
|||
template <typename T, typename Integer> |
|||
struct counting_pair{ |
|||
private: |
|||
typedef counting_pair self; |
|||
|
|||
public: |
|||
T& value; |
|||
Integer index; |
|||
|
|||
counting_pair(T& v, Integer i) : value(v), index(i) {} |
|||
counting_pair(const self& copy) : value(copy.value), index(copy.index) {} |
|||
}; |
|||
|
|||
// It's only forward for the moment
|
|||
template <typename Iterator, typename Integer> |
|||
struct counting_iterator : public std::iterator<std::forward_iterator_tag, counting_pair<typename std::iterator_traits<Iterator>::value_type, Integer>> { |
|||
private: |
|||
typedef counting_iterator self; |
|||
typedef counting_pair<typename std::iterator_traits<Iterator>::value_type, Integer> value_type; |
|||
|
|||
Iterator it; |
|||
Integer count; |
|||
|
|||
public: |
|||
counting_iterator(Iterator it) : it(it), count(0) {} |
|||
counting_iterator(const self& copy) : it(copy.it), count(copy.count) {} |
|||
|
|||
self& operator++(){ |
|||
++it; |
|||
++count; |
|||
return *this; |
|||
} |
|||
|
|||
self operator++(int){ |
|||
self copy(*this); |
|||
++*this; |
|||
return copy; |
|||
} |
|||
|
|||
bool operator==(const self& rhs){ |
|||
return it == rhs.it; |
|||
} |
|||
|
|||
bool operator!=(const self& rhs){ |
|||
return it != rhs.it; |
|||
} |
|||
|
|||
typename self::value_type operator*() { |
|||
return counting_pair<typename std::iterator_traits<Iterator>::value_type, Integer>(*it, count); |
|||
} |
|||
}; |
|||
|
|||
template <typename Container, typename Integer> |
|||
struct counting_container { |
|||
private: |
|||
typedef counting_container self; |
|||
typedef typename Container::iterator backing_iterator; |
|||
Container* backing_container; |
|||
|
|||
public: |
|||
typedef counting_iterator<backing_iterator, Integer> iterator; |
|||
|
|||
counting_container(Container& v) : backing_container(std::addressof(v)) {} |
|||
counting_container(const self& x) : backing_container(x.backing_container) {} |
|||
|
|||
iterator begin() { |
|||
return iterator(backing_container->begin()); |
|||
} |
|||
|
|||
iterator end() { |
|||
return iterator(backing_container->end()); |
|||
} |
|||
}; |
|||
|
|||
template <typename Integer = int, typename Container> |
|||
counting_container<Container, Integer> counted(Container& c){ |
|||
return counting_container<Container, Integer>(c); |
|||
} |
|||
|
@ -0,0 +1,21 @@ |
|||
#include "counting_iterator.hpp" |
|||
#include <vector> |
|||
#include <iostream> |
|||
|
|||
int main(){ |
|||
std::vector<int> v{1,3,37,1337,7}; |
|||
|
|||
for(auto x : counted(v)){ |
|||
std::cout << "v[" << x.index << "] = " << x.value << std::endl; |
|||
} |
|||
|
|||
for(auto x : counted(v)){ |
|||
x.value *= x.index; |
|||
} |
|||
|
|||
for(auto x : counted(v)){ |
|||
std::cout << "v[" << x.index << "] = " << x.value << std::endl; |
|||
} |
|||
|
|||
return 0; |
|||
} |
Reference in new issue