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