2009-06-30 8 views
7

J'ai écrit mon propre modèle de conteneur avec un itérateur. Comment implémenter const_iterator?C++: Comment écrire un const_iterator?

template <class T> 
class my_container { 
private: 
    ... 

public: 
    my_container() : ... { } 
    ~my_container() { } 

    class iterator : public std::iterator<std::bidirectional_iterator_tag, T> { 
    public: ... 

Répondre

4

La seule différence devrait être que lorsque vous dè référence const iterator vous obtenez une référence const plutôt que d'une référence à l'objet dans le récipient.

+1

Qu'en est-il des méthodes qui prennent les itérateurs comme arguments ou qui retournent les itérateurs? Je dois les surcharger pour const_iterators? On dirait un tas de code répété. –

+0

Les itérateurs devraient être convertibles en const_iterators, donc vous ne devrez pas surcharger si vous avez seulement besoin d'un const_iterator. Vous faites pour des fonctions comme begin(), end(), mais il n'y a pas moyen de contourner cela, car const fait aussi partie de la signature de la méthode. –

+2

@ Posoo Grubb: Non. Si vous avez des méthodes qui prennent des itérateurs, alors faites-en un modèle. La méthode devrait fonctionner pour tout ce qui agit comme un itérateur. Si la méthode nécessite un itérateur plutôt qu'un const_iterator, le compilateur générera l'erreur appropriée. –

2

Je trouve que la façon la plus simple d'implémenter des itérateurs est boost::iterator. Si vous voulez rouler votre propre, je pense que la signature devrait être:

class const_iterator : public std::iterator<std::bidirectional_iterator_tag, const T> { 

avec la mise en œuvre de la même (en supposant que vous utilisez reference_type et ainsi de suite dans vos signatures de fonction)

+0

J'ai été surpris de trouver que iterator_traits :: const_iterator> :: value_type est int, pas int const (T, au lieu de const T dans votre code). Je pense qu'avec const a plus de sens cependant. Cependant, la ligne de fond est si vous voulez faire correspondre avec les conteneurs standard, vous devez utiliser non-const. –

+0

La chose importante avec un const itéateur est que vous ne pouvez pas l'utiliser pour changer la collection étant itérée plus. Donc, T ou const T & sont appropriés. Utiliser const avec juste T n'est pas nécessaire (puisque le retour sera une copie) –

+0

Eh bien, si vous voulez spécifier que la valeur-by est non-const, vous devez spécifier tous les paramètres: class const_iterator: public std :: itérateur . J'irais avec brièveté (avec une protection supplémentaire contre les bugs d'assignation/égalité) plutôt que la conformité avec le vecteur STL, mais c'est un choix difficile du point de vue du design. –

0

Roger Pate, value_types sont "simple". Je suppose que vous verrez le const si vous regardez iterator_traits :: const_iterator> :: reference, que je pense sera "const int &".

Questions connexes