Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: tamat en 15 de Septiembre de 2006, 01:46:42 AM

Título: Templates y forzar los casts
Publicado por: tamat en 15 de Septiembre de 2006, 01:46:42 AM
Resulta que tengo un template VECTOR3 (lo uso para guardar puntos) que tiene como parametro el tipo de datos, uso floats generalmente pero en algunos casos necesito double. El problema es que algunas funciones necesitan mucha precisión en los points así que usan double.

Tengo definidos dos tipos:
typedef VECTOR3<float> point;
typedef VECTOR3<double> pointD;


El problema es que si una función espera un point y recibe un pointD me peta, el sistema no sabe hacer el cast de uno a otro.

Alguien puede echarme una mano? he probado esto:

point& operator = (point& p, pointD& pd)


pero no funciona.

Otro problema es que algunas funciones reciben un const point& p, si le paso un pointD puedo hacer que el sistema fuerce un cast?

Gracias
Título: Templates y forzar los casts
Publicado por: Prompt en 15 de Septiembre de 2006, 08:18:35 AM
pero donde está el código de sobrecarga del operador "="?

yo... haría algo así


point& operator = ( const pointD& pd )
{
   x = static_cast<float>(pd.x);
   y = static_cast<float>(pd.y);
   z = static_cast<float>(pd.z);
   return *this;
}


Tienes implementado algo así?
Título: Templates y forzar los casts
Publicado por: Warchief en 15 de Septiembre de 2006, 10:20:10 AM
Uhm, si la función admite distintos tipos de datos, ¿no debería ser una función template para el vector? (sin usar el typedef)


template <typename Type>
Type Foo( const VECTOR3<Type> &myVector ) {
 return myVector.x;
}

main() {
double a = Foo( myPointD );
float b = Foo( myPoint );
}
Título: Templates y forzar los casts
Publicado por: tamat en 15 de Septiembre de 2006, 06:28:47 PM
Cita de: "Prompt"pero donde está el código de sobrecarga del operador "="?

joer prompt... obviamente la tengo implementada, no la puse porque me parecia superflua.


Warchief, no pillo lo que quieres decir. Yo solo quiero que el compilador se encargue de hacer el cast de mytemplate<double> a mitemplate<float>.
Título: Templates y forzar los casts
Publicado por: pacomix en 15 de Septiembre de 2006, 06:42:41 PM
Creo que se podría tener un constructor de conversión explícito, con el tipo desde el que quieres convertir como único parámetro, en el template hacia el que se quiere convertir, y luego hacer un:

static_cast<tipo_a_convertir_con_constructor_de_conversión_explícito>(objeto_tipo_a_ser_convertido)

en la llamada a la función deseada.

No estoy muy seguro pero creo que se podría hacer así según he estado leyendo en la teoría.
Título: Re: Templates y forzar los casts
Publicado por: hotcamus en 15 de Septiembre de 2006, 10:27:20 PM
Cita de: "tamat"
El problema es que si una función espera un point y recibe un pointD me peta, el sistema no sabe hacer el cast de uno a otro.
Point y PointD son dos tipos completamente distintos, el compilador no sabe como convertir entre ellos por lo que tienes que proporcionar los métodos adecuados si quieres conversiones automáticas:


template <typename Type>
struct VECTOR3
{
 VECTOR3()
   : x (0), y(0), z(0) { }

 template <typename OtherType>
 VECTOR3(const OtherType &other)
 {
   *this = other;
 }
 
 template <typename OtherType>
 VECTOR3 &operator=(const OtherType &other)
 {
   x = static_cast<Type>(other.x);
   y = static_cast<Type>(other.y);
   z = static_cast<Type>(other.z);

   return *this;
 }

 Type x, y, z;
};

typedef VECTOR3<float> Point;
typedef VECTOR3<double> PointD;

void f(const Point &p)
{
}

void g(const PointD &pd)
{
}

int main(int, char **)
{
 Point p;
 PointD pd;

 f(p);
 f(pd);
 g(p);
 g(pd);

 return 0;
}



El constructor y operator= son templates cuyo tipo es distinto del que usas para instanciar VECTOR3 por lo que te permiten usar un VECTOR3<float> donde requieres un VECTOR3<double>.

Los static_cast te evitan los warnings cuando hay, por ejemplo, conversiones de float a int.

El problema es que esto genera variables temporales. Las llamadas f(pd) y g(p) construyen una variable temporal que es la que pasan al método. Si quieres evitar la creación de variables automáticas haz que el constructor sea "explicit":


 template <typename OtherType>
 explicit VECTOR3(const OtherType &other)
 {
   *this = other;
 }

 ...

 f(p);
 f(Point(pd));
 g(PointD(p));
 g(pd);



Espero que esto te sirva de ayuda.
Título: Templates y forzar los casts
Publicado por: tamat en 16 de Septiembre de 2006, 10:03:04 PM
Muchisimas gracias hoctamus, era exactamente eso lo que necesitaba. Había leido que se pueden usar funciones con un segundo parametro pero no sabía hacerlo.

Por cierto, me parece que el Visual 6 no permite hacer eso, sabes algo? yo uso el 2005 pero es para saber hasta donde llega la retrocompatibilidad de mi codigo.

Gracias de nuevo.
Título: Templates y forzar los casts
Publicado por: hotcamus en 17 de Septiembre de 2006, 09:38:22 PM
En eso no puedo ayudarte. Hace mucho que dejé el Visual 6 y no tengo ninguno a mano para comprobarlo.