Una de iteradores en C++
Ayer, mi colega Antares me planteó un problema (y yo no sé decir que no a los problemas). Está desarrollando un contenedor en el cuál necesita tener iteradores e iteradores constantes para recorrer los elementos. Probando los iteradores constantes, utilizó el siguiente código:
Contenedor c;
for(Contenedor::const_iterator it = c.begin(); it != c.end(); ++it)
{
...
}
Pero el compilador arrojaba el siguiente error:
contenedor.cpp:474: error: conversion from ‘Contenedor::iterator’ to non-scalar type ‘Contenedor::const_iterator’ requested
contenedor.cpp:474: error: no match for ‘operator!=’ in ‘ite != Contenedor::end()()’
contenedor.h:226: note: candidates are: bool Contenedor::const_iterator::operator!=(const Contenedor::const_iterator&) const
El escenario es el siguiente:
class Contenedor
{
private:
...
public:
Contenedor();
...
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
...
class iterator
{
private:
...
public:
friend class Contenedor;
iterator();
iterator operator++();
bool operator!=(const iterator & it) const;
iterator & operator=(const iterator & it) ;
};
...
class const_iterator
{
private:
...
public:
friend class Contenedor;
const_iterator();
const_iterator operator++();
bool operator!=(const const_iterator & it) const;
const_iterator & operator=(const const_iterator & it);
...
};
};
¿Dónde está el problema?
Cuando llamas al método begin() de tu clase contenedor, el compilador realiza una llamada al método begin() no-constante de tu clase. Como el objeto c no es constante, no hay forma de saber que se quiere utilizar el método begin() const.
Para solucionar esto podemos hacer un casting a operator, el cuál nos permite que un iterador sea convertido silenciosamente a un const_iterator. Realmente seguimos trabajando con begin() no-constante y con end() no-constante, pero la conversión del iterator es transparente.
La solución es tan sencilla como añadir a la clase iterator el siguiente método:
operator const_iterator() { return const_iterator(); }
También estuvimos barajando otra posibilidad, y fue la de añadir un operator= a iterator que recibiese un const_iterator, con lo cual, también se solucionaría el problema. La desventaja de esto, es que iterator necesitaría acceder a la parte interna de const_iterator.
Tags
La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.
