9
votes

Comment adapter une interface visiteur à une interface Itératrice?

Je me demande s'il existe un bon modèle de design ou idiome pour réaliser ce qui suit:

Vous avez une classe existante qui fournit uniquement une interface visiteur, comme suit P>

for(iterator it(...), ite(...); it != ite; ++it) {
  /* process node */
}


1 commentaires

Désolé d'abuser d'ici: litb, pouvez-vous rejoindre # ECO32?


3 Réponses :


6
votes

Dans l'affaire Général, je ne pense pas que ce soit possible, du moins pas proprement.

au moins comme il est généralement défini, un itérateur s'attend à gérer une collection homogène. C'est-à-dire, un itérateur est normalement défini quelque chose comme: xxx

... de sorte qu'un itérateur spécifique ne peut donc fonctionner qu'avec des éléments d'un type spécifique. Le plus que vous puissiez faire pour travailler avec des types différents est de créer un itérateur à (un pointeur / référence à) une classe de base, et de le laisser traiter avec des objets de classes dérivées.

par contraste, il est assez facile de écrire un visiteur comme ceci: xxx

Ceci peut visiter des nœuds de oneType ou autretype , même si les deux sont complètement indépendant. Fondamentalement, vous avez une fonction visiter dans votre classe de visiteurs pour chaque type de classe qu'il sera capable de visiter.

regardé de Une direction légèrement différente, un itérateur est essentiellement une forme spécialisée de visiteur qui ne fonctionne que pour un type d'objet. Vous échangez un peu plus de contrôle sur le modèle de visite en échange de la perte de la possibilité de visiter les types d'objets non liés.

Si vous n'avez besoin que si vous n'avez besoin que d'un type (même si un type peut être une classe de base, et les objets visités sont de différents types dérivés), puis la méthode évidente consisterait à créer une classe "pont" qui visit des objets ( arborescence nœuds, dans votre exemple), et quand sa visite est appelé, il suffit de copie l'adresse du nœud qui se rendit dans une collection qui prend en charge des itérateurs: xxx

Utilisation de ce processus serait un processus en deux étapes: premier Visitez les nœuds comme un visiteur normalement, après avoir collecté ensemble les nœuds d'intérêt que vous pouvez y parcourir, tout comme vous feriez une autre collection qui fournit des itérateurs. À ce stade, votre modèle de visitation n'est limité que par la classe d'itérateurs fournie par la collection que vous utilisez dans votre pont.


0 commentaires

2
votes

Bâtir la logique Traversal dans les implémentations des visiteurs n'est en effet pas flexible. Un moyen utilisable de séparer de manière proprement séparé des structures composites à partir de visites peut être effectuée via Combinateurs visiteurs < / a> (il y a d'autres papiers, n'hésitez pas à google pour eux).

Ces diapositives sur le même sujet peuvent également être d'intérêt. Ils expliquent comment obtenir la syntaxe propre à la boost :: spirit règles.


0 commentaires

3
votes

J'ai eu ce problème dans un cadre réel avec une implémentation R-Tree qui fournissait une interface visiteur, alors que j'avais besoin d'une interface Itératrice. La suggestion de Jerry ci-dessus ne fonctionne que si vous pouvez accepter de stocker tous les résultats dans une collection. Cela peut entraîner une consommation de mémoire élevée si votre jeu de résultats est énorme et que vous n'avez pas besoin de les stocker.

Une solution qui fonctionnera à coup sûr est de lancer le visiteur dans un fil séparé et de commencer à attendre une variable conditionnelle pour les résultats. Lorsqu'un appel de visite est effectué, vous stockez le résultat actuel dans un emplacement de température partagée et utilisez une autre variable conditionnelle pour attendre la demande suivante. Vous signalez la variable conditionnelle du fil de l'appelant (principal) avant d'attendre votre propre. L'appelant, qui met en œuvre l'interface Itératrice peut alors retourner la valeur stockée à l'emplacement Temp. Au cours de la prochaine itération, il pourrait signaler la variable conditionnelle du fil du visiteur et attendre seul pour l'élément suivant. Malheureusement, cela est un peu coûteux si vous le faites par article. Vous pouvez tamponner certains éléments pour améliorer la performance.

Ce que nous avons vraiment besoin est une pile supplémentaire et d'alterner entre deux contextes. Cette abstraction est fournie par les Coroutines. En C ++, Boost :: COROUTINE fournit une implémentation propre. Ci-dessous, j'inclus un exemple complet de la manière dont le motif de visiteur peut être adapté dans un motif d'itérateur. xxx


0 commentaires