Puis-je convertir un itérateur inverse, à un avant itérateur?
J'ai une classe appelée Action
, qui est essentiellement un wrapper autour d'une deque de Move
objets.
Parce que j'ai besoin de traverser la deque de Moves
à la fois en avant et en arrière, j'ai hâte d'itérateur et un reverse_iterator en tant que variables membres de la classe. La raison pour cela est parce que j'ai besoin de savoir quand je suis passé devant la "fin" de la deque, à la fois quand je suis aller en avant ou en arrière.
La classe ressemble à ceci:
class Action
{
public:
SetMoves(std::deque<Move> & dmoves) { _moves = dmoves; }
void Advance();
bool Finished()
{
if( bForward )
return (currentfwd==_moves.end());
else
return (currentbck==_moves.rend());
}
private:
std::deque<Move> _moves;
std::deque<Move>::const_iterator currentfwd;
std::deque<Move>::const_reverse_iterator currentbck;
bool bForward;
};
La Advance
fonction est la suivante:
void Action::Advance
{
if( bForward)
currentfwd++;
else
currentbck++;
}
Mon problème est que je veux être en mesure de récupérer un itérateur à l'actuel Move
objet, sans avoir à se demander si je vais vers l'avant ou vers l'arrière. Cela signifie une fonction renvoyant un type d'itérateur, mais j'ai deux types.
Dois-je oublier de retourner un itérateur, et retour const référence à un Move
objet à la place?
meilleurs vœux,
BeeBand
- La réponse à votre question "puis-je avoir un reverse_iterator à partir d'un avant itérateur" est oui et ici
Vous devez vous connecter pour publier un commentaire.
C'est exactement le genre de problème qui a motivé la conception de la STL pour commencer. Il y a de réelles raisons:
Je soupçonne ce que vous voyez maintenant est plus ou moins la pointe de l'iceberg de la réalité des problèmes. Mon conseil serait de prendre un peu de recul, et au lieu de se demander à propos de la façon de traiter avec les détails de la conception pour l'instant, de demander un peu plus d'une question d'ordre général à propos de ce que vous essayez d'accomplir, et la meilleure façon de réaliser que résultat final.
Pour ceux qui s'occupent principalement sur la question dans le titre, la réponse est très qualifié "oui". En particulier, un reverse_iterator a un
base()
membre pour le faire. Les qualifications sont un peu cependant problématique.Le démontrer le problème, considérons le code comme ceci:
L'exécution de cette à ce moment-là sur ma machine produit la sortie suivante:
Résumé: avec
rbegin()
nous doit ajoutez-en un avant de se convertir à l'avant d'une itérateur pour obtenir un itérateur qui est valide -- mais avecrend()
nous devons pas ajoutez-en un avant de se convertir pour obtenir une valide itérateur.Aussi longtemps que vous utilisez
X.rbegin()
etX.rend()
que les paramètres d'un algorithme générique, c'est très bien-mais l'expérience indique que la conversion à l'avant itérateurs souvent conduit à des problèmes.En fin de compte, cependant, pour le corps de la question (plutôt que le titre), la réponse est à peu près comme donné ci-dessus: le problème vient d'essayer de créer un objet qui combine la collection avec un couple d'itérateurs dans cette collection. Résoudre ce problème, et l'ensemble de l'entreprise vers l'avant et inverse les itérateurs devient inutile.
Inverse des itérateurs ont un membre
base()
qui retourne un correspondant de l'avant itérateur. Méfiez-vous que ce n'est pas un itérateur qui se rapporte au même objet, il fait en réalité référence à l'objet suivant dans la séquence. C'est ainsi querbegin()
correspond àend()
etrend()
correspond àbegin()
.Donc, si vous voulez retourner un itérateur, alors vous devez faire quelque chose comme
Je préfère renvoyer une référence, même si, et expriment toute l'itération de détails à l'intérieur de la classe.
(currentbck+1).base()
borks quand currentbck est un itérateur. La conversion entre les deux est un monde d'erreurs en attente de se produire.Depuis
std::deque
est un accès aléatoire conteneur (le même questd::vector
) vous êtes beaucoup mieux d'utiliser un seul index entier dans le deque pour les deux traversals.Il me semble que vous disposez de deux comportements différents dans la même classe.
Notamment, il semble que vous ne pouvez parcourir votre collection en une seule commande, sinon, si vous étiez pour commencer le parcours, puis de changer le
bforward
argument vous vous retrouvez avec une étrange situation.Personnellement, je suis pour exposer les deux itérateurs (c'est à dire, avant
begin, end, rbegin and rend
).Vous pouvez également revenir un Itérateur simple objet:
Ensuite, vous pouvez simplement retourner ce simple objet:
Ou si vous voulez choisir dynamiquement entre l'avant et l'arrière de la traversée, vous pourriez faire Itérateur un pur interface virtuelle et ayant à la fois en avant et en arrière de la traversée.
Mais vraiment, je ne vois vraiment pas le point de stockage à la FOIS en avant et en arrière itérateur si il semble que vous n'utilisera qu'un seul :/
Action
classe, vous avez seulement besoin de passer leIterator
(ou si vous avez été à faire directement référence à la deque les itérateurs, la position actuelle et la fin). De cette façon, vous la promotion de découplage 🙂Peut-être vous devriez revoir votre choix du conteneur.
Habituellement, vous n'avez pas besoin d'inverser les itérateurs pour revenir en arrière,
permettra de revenir en arrière, tous les mais il pourrait ne pas fonctionner (qui je suppose que vous avez essayé) avec dequeue.
Ce que vous devriez vraiment faire est le modèle de votre classe ici en tant que décorateur de retirer et à mettre en œuvre votre propre Action des itérateurs. Ce serait ce que je ferais de toute façon.