Définir l’iterator de mon propre conteneur

Je suis confus avec certains concepts sur la définition de mon propre iterator:

À partir de ceci: http://www.cs.northwestern.edu/~riesbeck/programming/c++/stl-iterator-define.html , qui semble suggérer l’utilisation d’une classe d’iterator interne qui définit les opérateurs. Beaucoup d’autres héritent de l’ iterator classe de base pour redéfinir les opérateurs.

Je suis assez confus quant aux méthodes à utiliser. pourquoi y a-t-il

 typedef ptrdiff_t difference_type; 

Par exemple, au début de la définition de la classe de conteneur?

Merci beaucoup!

La spécification C ++ sur ce qu’est exactement un conteneur STL impose à tout type de conteneur STL de disposer de plusieurs champs différents. Certaines, comme begin() et end() , sont des fonctions, tandis que d’autres, comme un iterator , sont des types. Ces ressortingctions s’appliquent également aux iterators. Cela permet aux fonctions de modèle C ++ d’introspection sur leurs types d’arguments pour rechercher davantage de propriétés. Par exemple, tous les types d’iterators STL doivent définir un champ iterator_category contenant un type codant leurs capacités. De cette manière, les algorithmes STL peuvent avoir différentes implémentations de différentes fonctions en fonction de la puissance des iterators qu’ils acceptent. Un exemple de classe est la fonction distance , qui prend deux iterators et renvoie le nombre d’espaces entre eux. Si l’entrée est un faible ForwardIterator ou BidirectionalIterator cela fonctionne en faisant avancer les iterators et en comptant le nombre de pas effectués, ce qui se passe dans O (n). Si l’entrée est un RandomAccessIterator , les iterators peuvent simplement être soustraits pour obtenir le résultat dans O (1).

Heureusement, vous n’avez généralement pas besoin de lister explicitement tous les types de fichiers. Il y a un type d’utilitaire dans l’en-tête appelé iterator qui est paramétré sur de nombreux arguments différents. Si vous définissez un type d’iterator personnalisé, vous pouvez hériter d’ iterator pour importer toutes ces informations automatiquement. C’est essentiellement un moyen plus rapide d’avoir tous les typedef en place.

En ce qui concerne les opérateurs que vous devez surcharger, vous devez au minimum obtenir ++ (préfixe et suffixe), == != , * (Déréférencement du pointeur) et -> définis. Tous les types d’iterators supportent cela. Pour les iterators bidirectionnels ou supérieurs, vous devez également définir -- (préfixe et postfixe). Enfin, pour les iterators à access aléatoire, vous devez prendre en charge [] , + , += , - (sauvegarder plusieurs étapes et soustraire deux iterators), -= , < , > , <= et >= .

J'espère que cela t'aides!

Bien que la réponse de @ templattypedef soit exacte, je peux peut-être clarifier un peu la situation.

Un iterator est normalement défini comme une classe nestede dans le conteneur. std::iterator est généralement utilisé comme classe de base pour faciliter la définition de votre classe iterator. Vous n’avez jamais vraiment besoin d’utiliser std::iterator – c’est juste là pour faciliter le travail et (surtout) réduire la quantité de code que vous devez taper.

Bien que l’utilisation de std::iterator puisse aider avec les typedef , cela n’aide en rien l’implémentation réelle.

La bibliothèque Boost.Iterator a beaucoup de bonnes choses pour cela, et je suggérerai de lire à propos de boost :: iterator_adaptor qui réduit considérablement la quantité de code que vous devez taper pour définir un nouvel iterator par-dessus un ancien.