[C con Clase] problema sobrecargando << hacia stringstream

Pedro Mateo pedromateoa en gmail.com
Lun Mar 26 20:08:27 CEST 2007


magistral amigo mio!!

es impresionante el lenguaje c++

gracias por tomarte tanto molestias en darme una respuesta tan detallada
lo entendi todo tan bien como lo has explicados
gracias de nuevo








El día 26/03/07, Steven Davidson <steven en conclase.net> escribió:
>
> Hola Pedro,
>
> El pasado 2007-03-26 04:30:08, Pedro Mateo escribió:
>
> PM> /*
> PM>     saludo
> PM>     he creado una plantilla para poder sobrecargar << de mi clase a
> PM> cualquier otra
> PM>     esto funciona para cout pero no para stringstream
> PM>     en el siguiente codigo me explico mejor
> PM> */
> PM> #include <iostream>
> PM> #include <sstream>
> PM> using namespace std;
> PM> class miclase{
> PM>        public:
> PM>        template <typename T> friend
> PM>        T& operator<<(T& o, const miclase& x)     {  return o<<"esta es
> PM> miclase";}
> PM> };
> PM> main(){
> PM>     miclase x;
> PM>     cout<<x<<endl;  //esto me sale bien
> PM>     //   hasta aqui si no agrega las siguientes lineas el programa se
> PM> compila sin errores
> PM>     //   puede comentar las siguientes lineas para verificar lo que
> digo
> PM>       stringstream c;
> PM>     c<<x;
> PM>     cout<<c.str()<<endl;
> PM>         //     el punto es que la plantilla que funciona en
> cout<<x<<endl;
> PM>         //     entiendo que deberia funcionarme en c<<x;
> PM>         //     me da el siguiente error al compilar
> PM>         /*
> PM>                 test.cpp: In function 'T& operator<<(T&, const
> miclase&)
> PM> [with T = std::stringstream]':
> PM>                 test.cpp:23:   instantiated from here
> PM>                 test.cpp:12: error: inicialización inválida de la
> referencia
> PM> de tipo 'std::stringstream&' desde una expresión
> de                     tipo
> PM> 'std::basic_ostream<char, std::char_traits<char> >'
> PM>         */
> PM> }
>
> El error está en la función. Escribes:
>
> template <typename T>
> T& operator<<( T& o, const miclase& x )
> {
> return o << "esta es miclase";
> }
>
> El problema es que la clase 'stringstream' no tiene sobrecargada ningún
> operador. En este caso, no existe la siguiente definición:
>
> stringstream & operator<<( stringstream &, const char * );
>
> Pero sí existe la siguiente:
> ostream & operator<<( ostream &, const char * );
>
> Como la clase 'stringstream' hereda de 'iostream' y ésta hereda de
> 'istream' y 'ostream', entonces podemos usar objetos de 'stringstream' en
> cualesquier funciones y operadores sobrecargados de 'ostream' e 'istream.
> Esto es,
>
> stringstream ss;
>
> ss << "hola";
>
> Realmente, acabamos por hacer lo siguiente:
>
> ostream &os = ss;
> os << "hola";
>
> Es decir, terminamos por invocar el operador sobrecargado << de 'ostream'.
> Esto implica que se retornará una referencia a un objeto de tipo 'ostream',
> ya que usamos el operador sobrecargado para 'ostream'.
>
> Dicho lo anterior, el compilador nos muestra el error, ya que no hay
> posibilidad de convertir un objeto 'ostream' a 'stringstream'. Volviendo a
> tu función-plantilla:
>
> template <typename T>
> T& operator<<( T& o, const miclase& x )
> {
> return o << "esta es miclase";
> }
>
> vemos el error al usar 'stringstream', ya que se generará este operador
> sobrecargado:
>
> stringstream& operator<<( stringstream& o, const miclase& x )
> {
> return o << "esta es miclase";
> }
>
> Sin embargo, como ya he explicado, usamos el operador << de 'ostream'. Al
> final, la sobrecarga anterior termina por retornar una referencia a un
> objeto 'ostream', mientras que tu definición intenta retornar una referencia
> a un objeto 'stringstream'. O sea, el comportamiento es el siguiente:
>
> stringstream& operator<<( stringstream& o, const miclase& x )
> {
> ostream &__temp = o;
> __temp << "esta es miclase"; // ostream &operator<<( ostream &, const char
> * )
> stringstream &__ret = __temp;  // <--- ERROR
> return __ret;
> }
>
> El error está en que no existe la conversión de 'ostream' a
> 'stringstream'.
>
> Tenemos dos soluciones que podemos implementar:
>
> 1. Reescribir la definición de la plantilla para retornar la referencia
> correcta. Esto es,
>
> template <typename T>
> T& operator<<( T& o, const miclase& x )
> {
> o << "esta es miclase";
> return o;
> }
>
> 2. No usar el parámetro T tan genéricamente. O sea, restrinjamos el tipo
> T. Sugiero reescribir la definición de la plantilla de esta manera:
>
> template <typename T>
> basic_ostream<T>& operator<<( basic_ostream<T>& o, const miclase& x )
> {
> return o << "esta es miclase";
> }
>
> De esta manera, cualquier objeto (o referencia) de la clase-plantilla
> 'basic_ostream' puede tomar un objeto de la clase 'miclase'. Esto significa
> que cualquier objeto de la clase base o sus derivadas pueden hacer uso de
> este operador. En este caso, el parámetro T de la plantilla hace alusión al
> tipo de los elementos del canal que típicamente será 'char' o 'wchar_t'.
>
> Supongo que también puedes optar por definir ambas plantillas. Por
> ejemplo,
>
> template <typename T>
> T& operator<<( T& o, const miclase& x )
> {
> // Hacer algo aquí
> }
>
> template <typename T>
> basic_ostream<T>& operator<<( basic_ostream<T>& o, const miclase& x )
> {
> return o << "esta es miclase";
> }
>
> En este caso, definimos un operador general 'T' y otro especializado
> 'basic_ostream<T>'. Con la primera sobrecarga, podemos usar otros tipos de
> objetos, como por ejemplo,
>
> class MiOtraClase {...};
> ...
> miclase x;
> MiOtraClase moc;
>
> moc << x;
>
>
> Espero haber aclarado la duda.
>
> Steven
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20070326/8e557dfa/attachment.html>


Más información sobre la lista de distribución Cconclase