Newsgroup: it.comp.lang.c++
Titolo: Da const_iterator ad iterator

Recentemente mi sono scontrato con questo problema: supponiamo di avere 
una lista e un suo const_iterator: come fare se si devono richiamare dei 
metodi di list che prendono un iterator? Esempio stupido:
typedef std::list<int> mylist;
typedef mylist::const_interator const_iter;
typedef mylist::iterator iter;
void foo( mylist lst, const_iter it)
{
        lst.insert(it, 3); // errore
}
Meyers in Effective STL (Item 27) consiglia questo approccio:
iter j = lst.begin();
std::advance( j, std::distance<const_iter>(it, j) );
lst.insert( j, 3 );
Indubbiamente questo approccio funziona, ma nel caso di std::list ha 
complessita` lineare e ho l'impressione si possa fare meglio. Esistono 
delle alternative migliori?
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

Esistono delle alternative migliori?
Non credo... in ogni caso se ti e' stato passato un
const_iterator allora e' un po' strano che tu abbia
bisogno di fare operazioni che richiedono un iterator.
Nel ricevere un const iterator tu stai promettendo di
non modificare il container e se hai anche ricevuto
un reference al container per coerenza dovrebbe
trattarsi di un const reference (da cui tu non
dovresti poter ottenere un non-const iterator visto
che la versione di begin() che restituisce un itertor
e' quella non-const).
Andrea

 bisogno di fare operazioni che richiedono un iterator.
beh, non mi sembra tanto strano. Supponi ad esempio questo (che in 
effetti si avvicina molto al mio problema originale):
using namespace std;
class TextDocument
{
        list<string> txt;
public:
        typedef list<string>::const_iterator const_iterator;
        const_iterator begin() const { return txt.begin(); }
        const_iterator end() const { return txt.end(); }
        ...
        void replace_line(const_iterator line_to_be_replaced, const string& s);
};
La classe rappresenta un documento di testo e fornisce l'accesso agli 
iteratori costanti per permettere di esaminare il testo contenuto, 
mentre tutte le modifiche al testo si effettuano tramite metodi. 
Ovviamente la classe TextDocument ha tutto il diritto di modificare i 
propri membri, anche se il chiamante ha passato un const_iterator.


propri membri, anche se il chiamante ha passato un const_iterator.
Questo e' il punto chiave... con "const_iterator" la libreria
intende un iteratore che non permette di fare modifiche sia
direttamente che chiamando metodi del container; tu con
const_iterator sembri intendere qualcosa di diverso (ovvero
un iteratore che non permette di modificare direttamente ma
che permette di ottenere delle modifiche del container usando
metodi non-const).
Fra l'altro, come design, credo preferirei degli iteratori
incapsulati e non gli iteratori della libreria standard ...
facendo cosi' potresti anche dichiarare un iteratore standard
non const come (unico?) membro del tuo iteratore e implementare
la logica che descrivi facendo modifiche basate sui tuoi
iteratori const o sui tuoi const_iterator se vuoi dargli
questo significato (un "iterator" che sia "const" non e' la
stessa cosa di un "const_iterator").
Andrea
PS:
  Non molto tempo fa mi sono trovato a farmi questa domanda
  blasfema... quante volte la const-correctness mi ha
  realmente semplificato la vita ?

   realmente semplificato la vita ?
beh, a me poche volte dato che la mia esperienza e` decisamente 
limitata. Pero` la const-correctness mi sembra una gran bella cosa.
