OVH Cloud OVH Cloud

list, autoptr, et consort

2 réponses
Avatar
Benoit Rousseau
J'ai des objets stockés dans une liste. Si l'objet vient à manquer
d'energie, il meurt.
J'ai donc la fonction
void Object::die() {
...
the_list.remove( this );
}

Le problème, c'est que je perd la reférence sur cet objet puisqu'il
n'est plus dans la liste. J'ai pensé qu'un autoptr m'aiderait :

//Code approximatif bien sur
list< autoptr<Object> > the_list;
list<..>::iterator li;
for( li = the_list.begin(); ... ) {
autoptr p = (*li);
p->move(); //Faire bouger l'objet (il peut perdre de l'energie et
//en faire perdre à d'autres objets)
}

Je garde bien la référence, même si je supprime l'objet de la liste?
Le but est qu'un objet n'interagisse plus avec les autres une fois qu'il
est mort.
Dans move(), l'objet vérifie s'il entre en contact avec les autres
objets de la liste ==> perte d'energie.

Par contre, j'aurais toujours un problème si c'est l'élément que je fais
bouger qui meurt. Dans ce cas, (li) est effacé et je perd la chaine de
la liste...

Mes prédécésseurs avait implanté un template de liste qui ne me plaisait
pas trop et que j'avais retiré pour utiliser stl::list. Peut être que je
n'aurait pas du... (Elle recodait toute la stl::list mais l'itérateur
sautait à l'élément suivant si il était effacé).

Des conseils ?

--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

2 réponses

Avatar
Benoit Rousseau
Benoit Rousseau wrote:

Mes prédécésseurs avaient implanté un template de liste qui ne me
plaisait pas trop et que j'avais retiré pour utiliser stl::list. Peut
être que je n'aurait pas du... (Elle recodait toute la stl::list mais
l'itérateur sautait à l'élément suivant si il était effacé).


Une petite note : j'utilisais pour ma part deux listes/queues. Je
retirais la tête et la plaçais dans l'autre queue.
Cette solution ne me plait plus non plus.

Des conseils ?




--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/

Avatar
Benoit Rousseau
Benoit Rousseau wrote:
J'ai des objets stockés dans une liste. Si l'objet vient à manquer
d'energie, il meurt.
J'ai donc la fonction
void Object::die() {
...
the_list.remove( this );
}

Le problème, c'est que je perd la reférence sur cet objet puisqu'il
n'est plus dans la liste. J'ai pensé qu'un autoptr m'aiderait :

//Code approximatif bien sur
list< autoptr<Object> > the_list;
list<..>::iterator li;
for( li = the_list.begin(); ... ) {
autoptr p = (*li);
p->move(); //Faire bouger l'objet (il peut perdre de l'energie et
//en faire perdre à d'autres objets)
}

Par contre, j'aurais toujours un problème si c'est l'élément que je fais
bouger qui meurt. Dans ce cas, (li) est effacé et je perd la chaine de
la liste...



Voici ce que j'ai implanté pour essayé d'y remédier : Un itérateur qui
garde la tête de la liste des objets à traiter :

class Arena {
protected:
list<Robot*> the_list; //Ma liste
list<Robot*>::iterator queue_head; //La tête de liste à traiter

public:
typedef list<Robot*>::iterator list_iterator;

void add_robot( Robot* r) {
//Je ne sais pas si cette fonction va poser des problemes
the_list.push_back( r );
}

/* Remove a robot from the_list. Move the head if the robot is the
head */
void remove_robot( Robot* r ) {
list_iterator to_remove;
if( (*queue_head) == r ) {
to_remove = queue_head++;
the_list.erase( to_remove );
} else {
the_list.remove( r );
}
}

/* Remettre la tête au debut de la liste */
list_iterator list_reset_head() {
queue_head = the_list.begin();
return queue_head++;
}

/* Retourner la tête puis la faire avancer pour le prochain coup */
list_iterator list_head() {
return (queue_head++);
}

/* Deplacer chacun des robots */
void move_all() {
list_iterator li;
for(li=list_reset_head(); li!=the_list.end(); li=list_head() ) {
Robot* robotp = (*li);
/* ...
Plus de problèmes si l'objet meurt pendant ce traitement...
*/
}
}
};

Le problème qui se pose maintenant, c'est que je n'ai qu'un seul
iterateur qui me permet de supprimer les éléments (si je dois retirer un
élément lors de deux boucles imbriquées, ca ne marche plus).

J'avais envisagé de faire quelquechose comme
class list_robot : public list<Robot*> {
iterator the_head; //La tête qui se promene...
//...
};

Mais je ne peux pas surcharger remove et erase...
Et ca ne resoud pas le probleme des boucles imbriquées.
Rem : Je me fiche pas mal des boucles imbriquées. Les suppressions ne
devraient pas se produire à ces moments là...


--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/