Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Duda sobre plantillas

Estas en el tema de Duda sobre plantillas en el foro de C/C++ en Foros del Web. Buenas, Disculpad por esta pregunta, que probablemente sea un poco tonta, pero me tiene sin poder continuar. He buscado por ahí y en el foro ...
  #1 (permalink)  
Antiguo 14/09/2010, 11:37
 
Fecha de Ingreso: octubre-2005
Mensajes: 42
Antigüedad: 18 años, 6 meses
Puntos: 0
Duda sobre plantillas

Buenas,


Disculpad por esta pregunta, que probablemente sea un poco tonta, pero me tiene sin poder continuar. He buscado por ahí y en el foro pero no consigo entender exactamente cómo hacerlo. Creo que la mejor forma de entender lo que quiero hacer es observar este breve fragmento de código:

Código:
template <typename General>

struct Gen {
	string name;
	General value;
};

typedef vector<Gen> Chain;


class Genoma {
protected:
	Chain genotype[2];

public:
	Genoma();
};
Entendámoslo como una estructura que simula el ADN. Primero creo una estructura que representa un gen, compuesta por un string y un valor que puede tomar cualquier tipo de datos, según el "template" creado al principio. "General" es ese tipo de datos cualquiera.

Una vez con el gen, me gustaría crear otro tipo personalizado llamado "Chain" (Cadena) que no es más que un vector de genes. De ahí el "typedef".

Por último, dentro de la clase "Genoma" quiero tener un array de dos "Chains", llamado "genotype". Pero estoy seguro de que no lo hago nada bien, puesto que da un par de errores y no tengo ni idea de cómo corregirlo.

¿Alguien puede ayudarme? Gracias!!!
  #2 (permalink)  
Antiguo 14/09/2010, 18:21
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Duda sobre plantillas

Hola,

si entiendo bien la cuestión, es un problema más complicado que parece.
El problema es casi más de logica antes que de compilación. El problema es el echo que no sabemos como manipular el tipo generico (el que llamaste General). Por ejemplo, si solo declaras un vector<General> ¿compila?

La solucion depende mucho de lo que querremos meter en en tipo General.

Todavia no he encontrado una solución que permite pasarse de una hierarquia en el tipo General, pero habra que echar un ojo en el boost::variant, y tambien quizas se puede hacer algo con la palabre clave "any" del c++0x, pero todavia no conozco ninguna solucion sencilla y poco especialisada.
__________________
Alicia: Sólo quiero saber que camino debo tomar.
Gato risón: Pues... depende mucho de donde quieras ir.

Mi página web

Última edición por r0d; 14/09/2010 a las 18:26
  #3 (permalink)  
Antiguo 14/09/2010, 21:54
Avatar de HackmanC  
Fecha de Ingreso: enero-2008
Ubicación: Guatemala
Mensajes: 1.817
Antigüedad: 16 años, 2 meses
Puntos: 260
Sonrisa Respuesta: Duda sobre plantillas

Hola,

Posiblemente,

Cita:
Iniciado por abadosa Ver Mensaje
... y un valor que puede tomar cualquier tipo de datos, según el "template" creado al principio ...

Una vez con el gen, me gustaría crear otro tipo personalizado llamado "Chain" (Cadena) que no es más que un vector de genes. ...
¿Genes de que tipo? Si estás especificando que van a ser Genes tienes que especificar de que tipo van a ser, de allí el template; y todos van a ser del mismo tipo.

Código C++:
Ver original
  1. typedef vector< Gen<string> > Chain;

Si lo que quieres es guardar en 'value' cualquier cosa .. eso es diferente.
Saludos,
  #4 (permalink)  
Antiguo 14/09/2010, 22:00
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 2 meses
Puntos: 22
Respuesta: Duda sobre plantillas

Recuerda que estás definiendo Gen como template, para que funcione el mecanismo debes indicarlo al compilador, por ejemplo:

Código:
typedef vector<Gen> Chain;
Es incorrecto, ¿Cómo sabe el compilador con que tipo de dato crear un Gen?.

Algo correcto sería:
Código:
typedef vector<Gen<int> > Chain; // value es un int
Lo siguiente debe de compilar:
Código C++:
Ver original
  1. #include <string>
  2. #include <vector>
  3.  
  4. template <typename General>
  5.  
  6. struct Gen {
  7.     std::string name;
  8.     General value;
  9. };
  10.  
  11. typedef std::vector<Gen<int> > Chain;
  12.  
  13.  
  14. class Genoma {
  15. protected:
  16.     Chain genotype[2];
  17.  
  18. public:
  19.     Genoma(){};
  20. };
  21.  
  22. int main(){
  23.     Genoma gen;
  24.     return 0;
  25. }
  #5 (permalink)  
Antiguo 15/09/2010, 04:36
 
Fecha de Ingreso: octubre-2005
Mensajes: 42
Antigüedad: 18 años, 6 meses
Puntos: 0
Respuesta: Duda sobre plantillas

Gracias! Es un poco lo que había pensado aunque...

Entiendo por vuestras respuestas que es imposible hacer que las "Chains" tengan Genes con el "value" de cualquier tipo indefinido. Tiene que ser siempre especificado en la creación del vector, como por ejemplo:

Código:
typedef vector<Gen<int> > Chain;
Vamos, no se puede hacer nada parecido que con Java, en el que podría usar Object.

EDITO -> Igual podría utilizar una "union" que contenga todos los tipos de datos que puede tomar General, pasar de los templates, y usar un discriminador dentro de la "union" para indicar a qué tipo de datos pertenece un valor. Algo así:

Código:
enum eGeneral { i, b, f, d, c };

struct General {
	eGeneral type;

	union {
		int iValue;
		bool bValue;
		float fValue;
		double dValue;
		char cValue;
	};
};

struct Gen {
	string name;
	General value;
};

typedef vector<Gen> Chain;


class Genoma {
protected:
	Chain genotype[2];

public:
	Genoma();
};

Última edición por abadosa; 15/09/2010 a las 04:54
  #6 (permalink)  
Antiguo 15/09/2010, 05:06
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Duda sobre plantillas

Se puede hacer algo parecido al java: hacer una clase madre para todos tus tipos General. Es lo que hace java con su super_object (Object).

Por ejemplo:
Código:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

struct ValueType
{
    virtual ~ValueType() {} // el destructor siempre virtual si la clase tiene que ser heredada
    virtual const int ToInt() const = 0;
    virtual const string ToStr() const = 0;
};

struct ValueType0 : public ValueType
{
    explicit ValueType0( int val = 0 ) : int_value( val ) {}

    const int ToInt() const { return int_value; 
    }

    const string ToStr() const {
        ostringstream oss;
        oss << int_value;
        return oss.str();
    }

protected:
    int int_value;
};

struct ValueType1 : public ValueType
{
    explicit ValueType1( const string & str = "n/a" ) : str_value ( str ) {}

    const int ToInt() const {
        istringstream iss( str_value );
        int ret_val;
        iss >> ret_val;
        return ret_val;
    }
    
    const string ToStr() const {
        return str_value;
    }

protected:
    string str_value;
};

//------------


struct Genoma
{
    ~Genoma() {
        for ( vector<ValueType*>::iterator it = values.begin(); it != values.end(); ++it )
            delete *it;
    }

    void PushValue( ValueType * value ) {
        values.push_back( value );
    }

    void PrintValue( size_t index ) {
        if ( index >= values.size() )
            cout << "index: " << index << " out of range" << endl;
        else
            cout << values[index]->ToStr() << endl;
    }

private:
    vector<ValueType*> values;
};

int main()
{    
    Genoma genoma;
    genoma.PushValue( new ValueType0( 109 ) );
    genoma.PushValue( new ValueType1( "test" ) );
    genoma.PrintValue(0);
    genoma.PrintValue(1);
    genoma.PrintValue(2);

    cout << endl << "end" << endl;
    cin.get();
    return 0;
}

Esta solución es tipicamente un enfoque "contrato". Es decir que todos los tipos que van a estar utilizados en la clase Genoma tienen que implementar la interfaz virtual del tipo mas alto (ValueType en mi ejemplo).

Existen otras soluciones, pero depiende lo que quieres hacer exactamente con estes values.

java permite esto, pero tiene un coste: cada objeto hereda del super_object (Object), y asi todos los objetos tienen una tabla virtual (en C++ solo los objetos que tienen funciones virtuales tienen una), y esta tabla virtual ya esta bien llena en java. Y esto implica perdidas en termino de rapidez de ejecución.

El c++ no tiene esta politica con los tipos, y para algunas cosas, hay que encontrar soluciones adaptadas. Por ejemplo, el problema de la reflexividad es complicado en C++, aunque en otros langajes (java o C# por ejemplo), no es un problema porque los tipos tienen datos en el runtime.
__________________
Alicia: Sólo quiero saber que camino debo tomar.
Gato risón: Pues... depende mucho de donde quieras ir.

Mi página web
  #7 (permalink)  
Antiguo 15/09/2010, 05:19
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Duda sobre plantillas

El problema de tu idea con una union, es que piedes la ventaja del polimorfismo (que permite manipular objetos sin conocer su tipo exacto).
Pero si quieres ir por este camino (que quizas es el bueno, depiende de tu contexto), lo que haria yo seria una lista de tipo utilizada con el boost::inplace_factory.
__________________
Alicia: Sólo quiero saber que camino debo tomar.
Gato risón: Pues... depende mucho de donde quieras ir.

Mi página web
  #8 (permalink)  
Antiguo 15/09/2010, 05:30
 
Fecha de Ingreso: octubre-2005
Mensajes: 42
Antigüedad: 18 años, 6 meses
Puntos: 0
Respuesta: Duda sobre plantillas

Wow, gracias!

Creo que con este código hago perfectamente lo que quiero hacer. Incluso se puede simplificar un poquito (los que tenemos nivel de C++ de "recién acabada la carrera" como yo no somos tan cracks) y entonces me va como anillo al dedo. Lo de "inplace_factory" no tengo ni idea de lo que es, así que casi mejor no tocarlo.

Gracias de nuevo!

Podéis cerrar el tema.
  #9 (permalink)  
Antiguo 15/09/2010, 05:36
Avatar de r0d
r0d
 
Fecha de Ingreso: noviembre-2007
Mensajes: 86
Antigüedad: 16 años, 5 meses
Puntos: 3
Respuesta: Duda sobre plantillas

Otra cosa:

antes de todo, tienes que contestar a esta cuestión: ¿como vas a utilizar los valores?
En tu caso, tenemos un Genoma que contiene varios Genes. ¿Porque estos Genes deben que llevar tipos de datos distintos?
Porque la cuestion es: si los Genes tienen valors de tipo distintos, ¿como (de un puto de vista de logica) se puede hacer un tratamiento "en serie" sobre eso?
Es el mismo problema en java: si tienes un contenedor con tipos distintos, estos tipos distintos tienen que tener algo en comun para poder hacer tratamientos en serie. Si me acuerdo bien, el Object java tiene funciones como ToString, o ToInt, etc. Esas funciones corresponden a una interfaz comùn (lo que he hecho con mi ValueType en mi ejemplo arriba).
__________________
Alicia: Sólo quiero saber que camino debo tomar.
Gato risón: Pues... depende mucho de donde quieras ir.

Mi página web

Etiquetas: plantillas
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 09:56.