Newsgroup: it.comp.lang.c++
Titolo: le STL non mi lasciano barare ...

Avrei bisogno di fare una piccola maialata
(lo ammetto, vengo dal C e uso il C++ solo quando mi servono le
strutture dati della STL, quindi purtroppo sono molto ignorante di C++
e disposto a produrre codice brutto sporco e cattivo, visto
che girera' solo per un paio di giorni e solo per me...)
Ho questa situazione (semplifico e ometto le varie #include etc.etc.):
una classe con una chiave e dei dati:
class Pippo { public: int Key,  Data;};
un set di Pippi:
set<Pippo> PipSet;
una funzione che lavora solo sul Data di un Pippo:
void Fai(Pippo *P) { P->Data++;}
quello che vorrei fare e' iterare sui Pippi di PipSet e passarli
alla funzione Fai:
for (set<Pippo>::iterator it=PipSet.begin(); it!=PipSet.end(); it++)
  Fai(it);
Per motivi assolutamente ragionevoli il compilatore non
mi fa fare questa cosa e mi da un messaggio del tipo
error: cannot convert 'std::_Rb_tree_const_iterator<Pippo>' to
'Pippo*'
infatti modificare un elemento del Set in generale e' male,
perche' se io modifico Key potrei trovarmi in una
situazione inconsistente.  Modificare Data e' innocuo, ma
il compilatore non lo sa e per sicurezza me lo impedisce.
Inutile dire che (dal basso della mia ignoranza) ho provato anche
a fare un cast:  Fai((Pippo *)it);
ma ci vuole ben altro per convincere il compilatore delle mie buone
intenzioni...
Domanda: esiste un modo per forzare il bastardo a fare quello che
voglio evitando l'ovvia soluzione di rimuovere il record dal set,
modificarlo e reinserirlo ?
Se non esiste un modo passero' da set<> a map<> che penso
mi permetta di fare quello che voglio, ma sono pigro ed eviterei
se posso...
grazie,
g.

 modificarlo e reinserirlo ?
SE la modifica a Data non modifica l'ordinamento del set puoi farlo in 
modo SICURO, con un semplice const cast:
for (set<Pippo>::iterator it=PipSet.begin(); it!=PipSet.end(); it++)
   Fai(const_cast<Pippo *>(&(*it)));
Se pero` modificare "Data" puo` modificare l'ordinamento ti ritrovi 
sicuramente con un set disordinato e quindi INUTILE.
Se pero` sei tu che fornisci la funzione di compare allora e` lecito 
fare il const cast per modificare una parte che non influenza il criterio.
In ogni caso l'alternativa:
map<key,Pippo> PipMap;
E' comunque piu` comoda e pulita :) (volendo puoi pure togliere key 
dalla classe Pippo)
--
Bye,
  Gabry

 dalla classe Pippo)
putroppo mi serve Key dentro Pippo perche' lo uso anche
in altri modi e ovunque come set mi andava bene, eccetto che
in quel punto critico.
Comunque ora col cast turbo va bene...
grazie a te (ed anche a Jonas per la solidarieta'...)
g.

 const_cast...
Okkio anche al &(*it) perche un iteratore NON e` necessariamente un 
pointer all'elemento, quindi se metti semplicemente it (come nel tuo 
esempio iniziale, Fai(it) ) potrebbe funzionare come no (piu` 
probabilmente no).
-- 
Bye,
  Gabry

 probabilmente no).
Questa l'ho sempre ritenuta una grandissima porcata.
Quando l'ho scoperto non ho più usato le STL per mesi...

    Fai(const_cast<Pippo *>(&(*it)));
A mio parere e' piu' pulito dichiarare Data come mutable, ed evitare
il const_cast. const_cast devi metterlo in tutti gli utilizzi, e
inibisce il controllo anche su Key. Dichiarando solo Data come
mutable, ottieni il risultato voluto, garantendo che Key non sia
variato.
--*PaN!*
 
-- 
I'm using an evaluation license of nemo since 242 days.
You should really try it!
http://www.malcom-mac.com/nemo

const_cast...
Essenzialmente "casta" in modo da rimuovere la "constness".