Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Enumerating C++ Range For
/// 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;
}
@eruffaldi
Copy link
Author

eruffaldi commented Nov 30, 2015

Possible improvement: the auto & q vs auto q, should be honered in a way to efficiently create pait<int,T&> or pair<int,T>.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment