2012-03-08 15 views
11

Come la domanda dice, mi sto chiedendo il motivo per questo. Perché ottengo un errore quando tento di ottenere la distanza tra gli iteratori const e non const.Perché std :: distance non funziona sul mix di iteratori const e nonconst?

vector<int> v; 
auto it=v.begin(); 
auto cit=v.cbegin(); 
distance(it,cit); 


no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&) 

Dalla mia comprensione limitata degli iteratori, non vedo alcuna ragione per cui non dovrebbe funzionare.

risposta

19

Si ha un iteratore mutabile e un iteratore costante nella chiamata a std::distance, pertanto la deduzione argomento modello non riesce. È possibile risolvere questo problema specificando esplicitamente l'argomento del modello.

std::vector<int> v; 
auto i1 = v.begin(); 
auto i2 = v.cbegin(); 

auto dist = std::distance<std::vector<int>::const_iterator>(i1, i2); 
6

Questo perché std::distance() richiede solo un parametro di modello:

template <class InputIterator> 
iterator_traits<InputIterator>::difference_type 
distance(InputIterator first, InputIterator last); 

Pertanto, first e last deve essere convertibile dello stesso tipo, e la risoluzione del modello, purtroppo, non ritengono che vector<int>::iterator è convertibile in vector<int>::const_iterator.

+0

hmm perché non creano semplicemente un modello con 2 parametri di modello? È possibile farlo in cpp core lang? Che cosa sto chiedendo è una decisione di progettazione o una limitazione lang? – NoSenseEtAl

+0

per essere chiari, so che possono creare template con 2 parametri di template, ma mi sto chiedendo sarebbe in conflitto con la versione 1 param template – NoSenseEtAl

+0

@NoSenseEtAl, direi la decisione di progettazione. In questo modo è più semplice e calcolare la distanza tra iteratori di tipi diversi (ad esempio un iteratore di accesso casuale e un iteratore diretto) non è probabilmente qualcosa che si desidera fare molto spesso. Potresti davvero scrivere una versione con due argomenti modello, ma quale sarebbe il problema del mondo reale? –

3

std::distance lavorerà con quei due iteratori ciò che non funziona è l'inferenza modello argomento. Il compilatore sta tentando di risolvere il tipo da sostituire per il primo argomento del modello e ha due potenziali candidati, che secondo lo standard finiscono in un errore.

Si può fare una delle due cose, o confrontare solo iteratori dello stesso tipo, o fornire il tipo al modello:

std::distance<std::vector<int>::const_iterator>(v.begin(), v.cbegin()); 
4

Come dicono tutti, è perché std::distance richiede solo un tipo di iteratore, e argomento deduzione argomento non è in grado di scegliere quale dovrebbe essere (anche se solo uno di essi è possibile dato che iterator converte in const_iterator ma non indietro).

forse vale la pena scrivere un modello simile a questa:

template <typename Container> 
typename Container::const_iterator constify(const Container &, typename Container::iterator it) { 
    return it; 
} 

Quindi è possibile forzare la detrazione modello come questo:

std::distance(constify(v, it), cit); 

invece di scrivere che tipo grande a lungo. Il parametro Container& è un peccato, è lì perché AFAIK Container non può essere dedotto da un argomento iteratore da solo.

Problemi correlati