2011-10-24 9 views
7

quindi ho una funzione chiamata find, che ha due versioni:Come utilizzare due funzioni, un'iteratore ritorno, l'altro const_iterator ritorno

template <typename T> 
typename btree<T>::iterator btree<T>::find(const T& elem) 
{ 
    //Implementation 
} 

e l'altro è la versione const_iterator:

template <typename T> 
typename btree<T>::const_iterator btree<T>::find(const T& elem) const 
{ 
    //Implementation 
} 

Nel mio file di prova quando faccio

btree<char>::iterator it = myTree.find('M'); 

Tutto funziona bene, ma quando uso il const_iterat o Versione:

btree<char>::const_iterator it = myTree.find('M'); 

Mi dà l'errore

error: conversion from 'btree_iterator' to non-scalar type 'const_btree_iterator' requested

Il che significa, ovviamente, che scoperta è sempre e solo con l'iteratore (non const) versione. So che il C++ dovrebbe chiamare automaticamente la versione const_iterator - se avessi fatto tutto bene. Quindi la domanda è: cosa potrei fare di sbagliato?

Le classi di iteratori sono:

class btree_iterator e class const_btree_iterator che è solo una pasta copia btree_iterator con i nomi cambiati

Ecco il codice sorgente completo:
btree_iterator.h (include const_btree_iterator) http://pastebin.com/zQnj9DxA
btree.h http://pastebin.com/9U5AXmtV
btree.tem http://pastebin.com/U9uV3uXj

+1

Sono visibili entrambe le versioni const e non-const dell'iteratore btree in cui si chiama myTree.find? puoi pubblicare l'intero file? – jopasserat

+0

Modificata la domanda con collegamenti al codice sorgente – Arvin

risposta

9

Tutti i contenitori standard implementano conversione del non-const a iteratori const (come specified in the requirements for the Container concept):

The type of iterator used to iterate through a container's elements. The iterator's value type is expected to be the container's value type. A conversion from the iterator type to the const iterator type must exist.

Hai bisogno di conversione costruttore in questo modo:

class btree_iterator; 
class const_btree_iterator 
{ 
     // .... 
     public: 
       const_btree_iterator(const btree_iterator& rhs) { /* .... */ } 
//optionally: const_btree_iterator& operator=(const btree_iterator& rhs) { /* .... */ } 
}; 

ho gettato l'operatore di assegnazione troppo ma suppongo è ridondante

+0

Grazie! Ha funzionato, e ho davvero pensato che il C++ avrebbe semplicemente chiamato la versione giusta di find in qualche modo, ma suppongo che non sia il caso – Arvin

+1

No. L'unico posto in cui so che la 'risoluzione di sovraccarico' appare a _backtrack_ e continuare a provare in C++ è nella famosa regola di SFINAE (in realtà non ignora gli overload, infatti: ignora le istanze dei template falliti) – sehe

5

Il bit importante è che la risoluzione di sovraccarico viene eseguita in base solo agli argomenti della funzione e non al risultato. Nel tuo caso particolare hai due diversi overload e la differenza è che l'implicito this è costante in uno di essi, che il sovraccarico verrà rilevato ogni volta che il tipo statico dell'oggetto o riferimento su cui viene chiamato il metodo è costante.

Se si vuole forzare la spedizione al sovraccarico costante, è possibile ottenere un riferimento const e quindi chiamare in quel di riferimento:

btree<char> const & r = myTree; 
btree<char>::const_iterator it = r.find('M'); 

si dovrebbe evitare questo costrutto nel codice vero e proprio, anche se lo si utilizza per scopi di test. La ragione è che i sovraccarichi const e non-const dovrebbero avere la stessa semantica e quindi il comportamento dovrebbe essere lo stesso.

Si noti inoltre che nei contenitori standard esiste una conversione implicita da iterator a const iterator per supportare l'utilizzo di const_iterator s direttamente su contenitori non const.Si dovrebbe fare lo stesso, vale a dire, se si fornisce una conversione implicita iterator-const_iterator, allora si può solo scrivere:

btree<char>::const_iterator it = myTree.find('M'); 

... e funzionerà (non metterà alla prova il metodo find, ma sarà ti consente di verificare il comportamento di const_iterator)

+0

Grazie per questo, I risolto usando una conversione da iteratore a const_iterator come hai menzionato – Arvin

+0

@Arvin Non mi è stato chiaro se * nel mio file di test * significasse che stavi provando a testare il sovraccarico const di find' o il const_iterator' o solo il contenitore in generale. –

+0

"nel mio file di test" significava all'interno della funzione principale in un file cpp separato che verifica la mia implementazione della classe btree. In realtà stavo testando il contenitore in generale e sono incappato in questo problema – Arvin