C++ Iteratori

Da Andreabont's Wiki.

Rendere una classe iterabile

Versione classica

#include <iostream>
#include <vector>
#include <iterator>

class mioContenitore {

private:
std::vector<int> v = {1,2,3,4,5};

public:

    class MyIterator : public std::iterator<std::input_iterator_tag, int> {
        
    private:
        int* p;
        
    public:
        
        /* ITERATOR METHODS */
        MyIterator(int* x) :p(x) {}
        MyIterator(const MyIterator& mit) : p(mit.p) {}
        MyIterator& operator++() {++p;return *this;}
        MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;}
        bool operator==(const MyIterator& rhs) {return p==rhs.p;}
        bool operator!=(const MyIterator& rhs) {return p!=rhs.p;}
        int& operator*() {return *p;}
        
    }; 

MyIterator begin() {
    return MyIterator(&v[0]);
}

MyIterator end() {
    return MyIterator(&v[0] + v.size());
} 
    
};

Versione C++17

Con C++17 il template std::iterator è stato deprecato, è necessario quindi scrivere esplicitamente gli iterator traits.

#include <iostream>
#include <vector>
#include <iterator>

class mioContenitore {

private:
std::vector<int> v = {1,2,3,4,5};

public:

    class MyIterator {
        
    private:
        int* p;
        
    public:
        
        /* ITERATOR TRAITS */
        using difference_type = int;
        using value_type = int;
        using pointer = const int*;
        using reference = const int&;
        using iterator_category = std::input_iterator_tag;
        
        /* ITERATOR METHODS */
        MyIterator(int* x) :p(x) {}
        MyIterator(const MyIterator& mit) : p(mit.p) {}
        MyIterator& operator++() {++p;return *this;}
        MyIterator operator++(int) {MyIterator tmp(*this); operator++(); return tmp;}
        bool operator==(const MyIterator& rhs) {return p==rhs.p;}
        bool operator!=(const MyIterator& rhs) {return p!=rhs.p;}
        int& operator*() {return *p;}
        
    }; 

MyIterator begin() {
    return MyIterator(&v[0]);
}

MyIterator end() {
    return MyIterator(&v[0] + v.size());
} 
    
};

Accesso agli iteratori

Versione Estesa

Usare le funzioni standard std:begin() e std::end() permette di eseguire il ciclo anche sugli array del C che non espongono i metodi begin ed end.

for (auto it = std::begin(vector); it != std::end(vector); ++it) {
   std::cout << "i = " << *it << std::endl;
}

Versione Compatta

for (auto &i : vector) { 
   std::cout << "i = " << i << std::endl;
}

Contatore basato su un range

E' possibile iterare direttamente su una lista di oggetti sfruttando gli initializer list.

for(int i : {1,2,3,4}) {
   cout << i << endl;
}