Created
November 30, 2015 16:27
-
-
Save eruffaldi/ac0f3d1189d39e237ce1 to your computer and use it in GitHub Desktop.
Enumerating C++ Range For
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Emanuele Ruffaldi | |
#include <vector> | |
#include <iostream> | |
#include <algorithm> | |
template <class VT, class IT> | |
class counter_class { | |
public: | |
using value_t = std::pair<int,VT>; | |
class iterator { | |
friend class counter_class; | |
public: | |
value_t operator *() const { return std::pair<int,VT>(i_,*it_); } | |
const iterator &operator ++() { ++i_; ++it_; return *this; } | |
iterator operator ++(int) { iterator copy(*this); ++it_; ++i_; return copy; } | |
bool operator ==(const iterator &other) const { return it_ == other.it_; } | |
bool operator !=(const iterator &other) const { return it_ != other.it_; } | |
protected: | |
iterator(IT it, int index) : i_ (index), it_(it) { } | |
private: | |
unsigned long i_; | |
IT it_; | |
}; | |
counter_class(IT b, IT e) : begin_(b),end_(e) {} | |
iterator begin() const { return iterator(begin_,0); } | |
iterator end() const { return iterator(end_,-1); } | |
IT begin_; | |
IT end_; | |
}; | |
template <class T, int N> | |
auto counted(const T data[N]) -> counter_class<T,T*> | |
{ | |
return counter_class<T&,T*>(&data,&data+N); | |
} | |
template <class It> | |
auto counted(It b, It e) -> counter_class<decltype(*b),It> | |
{ | |
return counter_class<decltype(*b),It>(b,e); | |
} | |
template <class T> | |
auto counted(std::initializer_list<T> args) -> counter_class<T,typename std::initializer_list<T>::iterator> | |
{ | |
return counter_class<T,typename std::initializer_list<T>::iterator>(args.begin(),args.end()); | |
} | |
// catches the previous and also the arrays | |
template <class CT> | |
auto counted(CT & ct) -> counter_class<decltype(*std::begin(ct)),decltype(std::begin(ct))> | |
{ | |
return counter_class<decltype(*std::begin(ct)),decltype(std::begin(ct))>(std::begin(ct),std::end(ct)); | |
} | |
// bonus | |
struct counter | |
{ | |
int first_; | |
int n_; | |
struct iterator | |
{ | |
int c_; | |
iterator(int c): c_(c) {} | |
int operator *() const { return c_; } | |
const iterator &operator ++() { ++c_; return *this; } | |
iterator operator ++(int) { iterator copy(*this); ++c_; return copy; } | |
bool operator ==(const iterator &other) const { return c_ == other.c_; } | |
bool operator !=(const iterator &other) const { return c_ != other.c_; } | |
}; | |
counter(int first, int n) :first_(first),n_(n) {} | |
iterator begin() { return iterator(first_); } | |
iterator end() { return iterator(first_+n_); } | |
}; | |
///----------------------------------------- | |
/// Example Start | |
template <class F,class L> | |
std::ostream & operator << (std::ostream & os, const std::pair<F,L> & p) | |
{ | |
os << "(" << p.first << "," << p.second << ")"; | |
return os; | |
} | |
struct Example2 | |
{ | |
std::vector<int> q; | |
using iterator = decltype(q)::iterator; | |
}; | |
Example2::iterator begin(Example2 & a) { return a.q.begin(); } | |
Example2::iterator end(Example2 & a) { return a.q.end(); } | |
struct Example | |
{ | |
std::vector<int> q; | |
using iterator = decltype(q)::iterator; | |
iterator begin() {return q.begin(); } | |
iterator end() {return q.end(); } | |
}; | |
int main(int argc, char * argv[]) | |
{ | |
std::vector<int> w; | |
w.push_back(10); | |
w.push_back(30); | |
w.push_back(40); | |
int w2 [] = {10,20,30,40}; | |
Example e; | |
e.q = w; | |
Example e2; | |
e2.q = w; | |
std::cout << "vector container\n"; | |
for(auto && q: counted(w)) | |
std::cout << q << std::endl; | |
std::cout << "init list\n"; | |
for(auto && q: counted({10,20,30,40})) | |
std::cout << q << std::endl; | |
std::cout << "array\n"; | |
for(auto && q: counted(w2)) | |
std::cout << q << std::endl; | |
std::cout << "iterator pair\n"; | |
for(auto && q: counted(w.begin(),w.end())) | |
std::cout << q << std::endl; | |
std::cout << "with begin/end members\n"; | |
for(auto && q: counted(e)) | |
std::cout << q << std::endl; | |
std::cout << "with begin/end function\n"; | |
for(auto && q: counted(e2)) | |
std::cout << q << std::endl; | |
std::cout << "count only\n"; | |
for(auto && q: counter(5,20)) | |
std::cout << q << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Possible improvement: the auto & q vs auto q, should be honered in a way to efficiently create pait<int,T&> or pair<int,T>.