59 votes

syntaxe foreach c++11 et itérateur personnalisé

J'écris un itérateur pour un conteneur qui est utilisé à la place d'un conteneur STL. Actuellement, le conteneur STL est utilisé à de nombreux endroits avec la balise syntaxe foreach c++11 eg : for(auto &x: C) . Nous avons dû mettre à jour le code pour utiliser une classe personnalisée qui englobe le conteneur STL :

template< typename Type>
class SomeSortedContainer{
    std::vector<typename Type> m_data; //we wish to iterate over this
    //container implementation code
};    
class SomeSortedContainerIterator{
    //iterator code
};

Comment faire pour qu'auto utilise l'itérateur correct pour le conteneur personnalisé afin que le code puisse être appelé de la manière suivante :

SomeSortedContainer C;
for(auto &x : C){
    //do something with x... 
}

En général, que faut-il faire pour s'assurer que auto utilise le bon itérateur pour une classe ?

51voto

R. Martinho Fernandes Points 96873

Vous avez deux choix :

  • vous fournissez des fonctions membres nommées begin et end qui peut être appelé comme C.begin() et C.end() ;
  • sinon, vous fournissez des fonctions gratuites nommées begin et end qui peuvent être trouvés en utilisant la recherche dépendante des arguments, ou dans l'espace de noms std et peut être appelé comme begin(C) et end(C) .

51voto

Mooing Duck Points 27497

Pour pouvoir utiliser l'intervalle pour, votre classe doit fournir const_iterator begin() const et const_iterator end() const membres. Vous pouvez également surcharger la fonction globale begin mais, à mon avis, il est préférable d'avoir une fonction membre. iterator begin() et const_iterator cbegin() const sont également recommandés, mais pas obligatoires. Si vous voulez simplement itérer sur un seul conteneur interne, c'est VRAIMENT facile :

template< typename Type>
class SomeSortedContainer{

    std::vector<Type> m_data; //we wish to iterate over this
    //container implementation code
public:
    typedef typename std::vector<Type>::iterator iterator;
    typedef typename std::vector<Type>::const_iterator const_iterator;

    iterator begin() {return m_data.begin();}
    const_iterator begin() const {return m_data.begin();}
    const_iterator cbegin() const {return m_data.cbegin();}
    iterator end() {return m_data.end();}
    const_iterator end() const {return m_data.end();}
    const_iterator cend() const {return m_data.cend();}
};    

Cependant, si vous voulez itérer sur quelque chose de personnalisé, vous devrez probablement concevoir vos propres itérateurs en tant que classes dans votre conteneur.

class const_iterator : public std::iterator<random_access_iterator_tag, Type>{
    typename std::vector<Type>::iterator m_data;
    const_iterator(typename std::vector<Type>::iterator data) :m_data(data) {}
public:
    const_iterator() :m_data() {}
    const_iterator(const const_iterator& rhs) :m_data(rhs.m_data) {}
     //const iterator implementation code
};

Pour plus de détails sur l'écriture d'une classe d'itérateur, voir ma réponse ici .

7voto

dspeyer Points 972

Comme d'autres l'ont dit, votre conteneur doit mettre en œuvre begin() et end() (ou avoir des fonctions globales ou std:: qui prennent des instances de votre conteneur comme paramètres).

Ces fonctions doivent retourner le même type (généralement container::iterator mais il ne s'agit que d'une convention). Le type retourné doit implémenter operator* , operator++ et operator!= .

2voto

Christian Rau Points 29137

A ma connaissance SomeSortedContainer doit simplement fournir begin() et end() . Et ceux-ci devraient retourner un itérateur standard conforme, dans votre cas SomeSortedContainerIterator qui envelopperait en fait un std::vector<Type>::iterator . Par conforme à la norme, j'entends qu'il doit fournir les opérateurs d'incrémentation et de déréférencement habituels, mais aussi tous les éléments suivants value_type , reference_type ... qui sont à leur tour utilisés par la construction foreach pour déterminer le type sous-jacent des éléments du conteneur. Mais vous pourriez vous contenter de les transmettre depuis le std::vector<Type>::iterator .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X