Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

erase entre un list::iterator et un list:reverse_iterator ???

2 réponses
Avatar
Aurélien Barbier-Accary
Tout est dans le titre...

Mais tout d'abord bonjour !
Je souhaite supprimer un ensemble d'objets contenus dans une liste doublement
chaînée. Pour trouver les bornes de suppression, je parcours la liste dans les
deux sens et j'utilise (donc) un itérateur normal et un itérateur inversé.
Mon souci est que je ne peux pas utiliser directement ces itérateurs pour faire
un erase :-(

Voici en code schématiquement mon pb :
list<T>::iterator it;
list<T>::reverse_iterator rit;
bool ok = false;
for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++)
[... -> ok=true ...]
ok = false;
for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++)
[... -> ok=true ...]
// Rq: je suis sûr que it et rit ne se croisent pas !
maliste.erase(it,rit);

Comment faire pour obtenir deux itérateurs de même type à partir de it et de rit ?
Merci d'avance pour vos conseils.

--
Aurélien Barbier-Accary

2 réponses

Avatar
Aurélien Barbier-Accary
maliste.erase(it,(++rit).base());
J'ai bon ?! :-)

Pour ceux qui se demandent, j'ai lu que maliste.erase(it,--rit.base()); pouvait
ne pas compiler avec certains compilateurs pour des vecteurs et des string (à la
place d'une liste).
Pour la doc de la fonction base(), voir
http://www.sgi.com/tech/stl/ReverseIterator.html

--
Aurélien Barbier-Accary
Avatar
kanze
Aurélien Barbier-Accary wrote:
Tout est dans le titre...

Je souhaite supprimer un ensemble d'objets contenus dans une
liste doublement chaînée. Pour trouver les bornes de
suppression, je parcours la liste dans les deux sens et
j'utilise (donc) un itérateur normal et un itérateur inversé.
Mon souci est que je ne peux pas utiliser directement ces
itérateurs pour faire un erase :-(

Voici en code schématiquement mon pb :
list<T>::iterator it;
list<T>::reverse_iterator rit;
bool ok = false;
for(it = ++maliste.begin(); (!ok) && (it!= maliste.end()); it++)
[... -> ok=true ...]
ok = false;
for(rit = ++maliste.rbegin(); (!ok) && (rit!= maliste.rend()); rit++)
[... -> ok=true ...]
// Rq: je suis sûr que it et rit ne se croisent pas !
maliste.erase(it,rit);

Comment faire pour obtenir deux itérateurs de même type à
partir de it et de rit ?


Il faudrait extraire la base de l'itérateur inverse. Ensuite, il
faudrait lui appliquer des corrections, selon que l'élément
trouvé doit en faire partie des éléments extraits ou non. (Selon
le cas, il pourrait aussi falloir une correction à l'itérateur
normal.)

Attention aussi ! Dans ton exemple, tu pourrais facilement
rencontrer un comportement indéfini. Mieux vaut utiliser
l'itérateur trouvé dans la première boucle comme itérateur d'end
de la deuxième. Quelque chose du genre :

typedef list<T> List ;
typedef List::iterator Iter ;

Iter bottom = std::find_if( l.begin(), l.end(),
bottomCondition ) ;
if ( bottom == l.end() ) {
// Non trouvé, que faire (une exception, peut-être)
}
Iter top = std::find_if( l.rbegin(),
List::reverse_iterator( bottom ),
topCondition ).base() ;
if ( top == bottom ) {
// Non truové...
}
if ( ! conditionsInclusives && top != bottom ) {
-- top ; // se positionne sur le dernier élément
if ( top != bottom ) {
++ bottom ; // et au delà du premier élément,
} // pour ne pas les effacer.
}
l.erase( bottom, top ) ;

Reste la question de ce que tu veux faire si les récherches
échouent. (Le code ici n'efface rien dans ce cas-là. Encore que
c'est à vérifier -- je ne me suis pas penché trop sur les
conditions limites.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34