From 39318cf12bde973d0880b02ada5dfed06320b77e Mon Sep 17 00:00:00 2001 From: "Joshua Moerman (@Kassalade)" Date: Sun, 22 May 2011 17:13:03 +0200 Subject: [PATCH] first draft of counting range-based-for-loops --- iterators/counting_iterator.hpp | 97 +++++++++++++++++++++++++++++++++ iterators/main.cpp | 21 +++++++ 2 files changed, 118 insertions(+) create mode 100644 iterators/counting_iterator.hpp create mode 100644 iterators/main.cpp diff --git a/iterators/counting_iterator.hpp b/iterators/counting_iterator.hpp new file mode 100644 index 0000000..462ab86 --- /dev/null +++ b/iterators/counting_iterator.hpp @@ -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 + +// A reference is a struct, yuk... +// Maybe a proxy is better +template +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 +struct counting_iterator : public std::iterator::value_type, Integer>> { +private: + typedef counting_iterator self; + typedef counting_pair::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::value_type, Integer>(*it, count); + } +}; + +template +struct counting_container { +private: + typedef counting_container self; + typedef typename Container::iterator backing_iterator; + Container* backing_container; + +public: + typedef counting_iterator 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 +counting_container counted(Container& c){ + return counting_container(c); +} + diff --git a/iterators/main.cpp b/iterators/main.cpp new file mode 100644 index 0000000..7b9f8d0 --- /dev/null +++ b/iterators/main.cpp @@ -0,0 +1,21 @@ +#include "counting_iterator.hpp" +#include +#include + +int main(){ + std::vector 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; +}