2011-10-24 12 views
7

Así que tienen una función llamada hallazgo, que tiene dos versiones:Cómo utilizar dos funciones, una iterador de regresar, la otra const_iterator regresar

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

y la otra es la versión const_iterator:

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

En mi archivo de prueba cuando lo haga

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

Todo funciona bien, sin embargo, cuando se utiliza la const_iterat o la versión:

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

Me da el error

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

Lo que obviamente significa que hallazgo es solamente siempre utilizando el iterador (no const) versión. Sé que se supone que C++ llame a la versión const_iterator automáticamente, si hubiera hecho todo bien. Entonces la pregunta es, ¿qué podría estar haciendo mal?

Las clases son iterador:

class btree_iterator y class const_btree_iterator que es sólo una copia de pasta btree_iterator con los nombres cambiados

Éstos son el código fuente completo:
btree_iterator.h (incluye const_btree_iterator) http://pastebin.com/zQnj9DxA
btree.h http://pastebin.com/9U5AXmtV
btree.tem http://pastebin.com/U9uV3uXj

+1

¿Están visibles las versiones const y non const del iterador btree donde llama a myTree.find? ¿puedes publicar el archivo completo? – jopasserat

+0

Editado la pregunta con enlaces al código fuente – Arvin

Respuesta

9

Todos los contenedores estándar implementar la conversión de no constante a iteradores const (como 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.

Es necesario constructor de conversión de este 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) { /* .... */ } 
}; 

me tiró en el operador de asignación también, pero supongo es redundante

+0

¡Gracias! Eso funcionó, y realmente pensé que C++ simplemente llamaría a la versión correcta de find de alguna manera, pero supongo que ese no es el caso – Arvin

+1

No. El único lugar donde sé que 'resolución de sobrecarga' parece _backtrack_ y sigo intentando en C++ está en la famosa regla SFINAE (en realidad no está ignorando sobrecargas, de hecho: está ignorando las instancias de plantilla fallidas) – sehe

5

El punto importante aquí es que la resolución de sobrecarga se realiza basándose únicamente en los argumentos de la función y no en el resultado. En su caso particular tiene dos sobrecargas diferentes y la diferencia es que el this implícito es constante en uno de ellos, esa sobrecarga se recogerá siempre que el tipo estático del objeto o referencia sobre el que se llama el método sea constante.

Si desea forzar el envío a la sobrecarga constante, se puede obtener una referencia constante y luego llamar a esa referencia:

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

usted debe evitar este constructo en el código real, incluso si usted lo usa durante fines de prueba. La razón es que las sobrecargas const y no const deberían tener la misma semántica y, por lo tanto, el comportamiento debería ser el mismo.

También tenga en cuenta que en los contenedores estándar, hay una conversión implícita de iterator a const iterator para admitir el uso de const_iterator s directamente en contenedores no const.Usted debe hacer lo mismo, es decir, si se proporciona una conversión implícita iterator-const_iterator, a continuación, puedes escribir:

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

... se ponga a funcionar (no pondrá a prueba el método find, sino que le permiten verificar el comportamiento const_iterator)

+0

Gracias por esto, yo lo arreglé usando una conversión de iterador a const_iterator como mencionaste – Arvin

+0

@Arvin No estaba claro para mí si * en mi archivo de prueba * significaba que intentabas probar la sobrecarga de const 'find' o el' const_iterator' o solo el contenedor en general. –

+0

"en mi archivo de prueba" significa dentro de la función principal en un archivo cpp independiente que prueba mi implementación de clase btree. De hecho, estaba probando el contenedor en general y tropecé con este problema – Arvin

Cuestiones relacionadas