Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Templates y forzar los casts

Iniciado por tamat, 15 de Septiembre de 2006, 01:46:42 AM

« anterior - próximo »

tamat

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
Por un stratos menos tenso

Prompt

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í?

Warchief

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 );
}

tamat

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>.
Por un stratos menos tenso

pacomix

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.
=El verdadero guerrero de la luz se levanta cuando todos los demás han caído=-

hotcamus

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.

tamat

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.
Por un stratos menos tenso

hotcamus

En eso no puedo ayudarte. Hace mucho que dejé el Visual 6 y no tengo ninguno a mano para comprobarlo.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.