El problema al que se enfrenta tiene que ver con T
de pie ya sea para int
o float
.
Si nos fijamos en la definición de clase de plantilla, podrás notar que la misma T
que aparece después de typename
en la parte template
aparece también como parámetro al método Set
.
Esto significa que cuando se habla de Point<int>
entonces sólo hay uno Set
método definido, que tiene dos int
. Y cada Point<T>
diferente tendrá su propio método Set(T,T)
.
Si usted desea para una Set
método diferente, entonces tiene que declarar una plantilla Set
dentro de la clase de plantilla, esto se hace de la siguiente manera:
template <typename T>
class Point
{
public:
template <typename Num>
void Set(Num x, Num y);
};
Nota cómo tuviera que elegir un nombre de parámetro de plantilla diferente .
Con el fin de resolver el problema, se podría introducir otro método, por float
, pero entonces tendría que tener otro para double
, y long double
... Es muy pronto va a ser difícil.
La solución más simple, es ir de fuerza bruta:
template <typename Integral>
template <typename Num>
void Point<Integral>::Set(Num x, Num y)
{
this->x = long double(x) + 0.5;
this->y = long double(y) + 0.5;
}
Para int
y otros, sobre todo es inútil, pero funciona. Para los puntos flotantes, usamos el tipo de coma flotante más grande disponible para evitar perder precisión y luego realizamos el redondeo.
Obviamente, no funciona si de repente queremos un Point<float>
, por lo tanto, necesitamos una solución más inteligente, basada en los rasgos de tipo. La clase std::numeric_limits<T>
tiene un is_integer
que precisa si se trata o no de un tipo integral.
template <typename T>
template <typename Num>
void Point<T>::Set(Num x, Num y)
{
if (std::numeric_limits<T>::is_integer &&
!std::numeric_limits<Num>::is_integer)
{
this->x = x + 0.5;
this->y = y + 0.5;
}
else
{
this->x = x;
this->y = y;
}
}
}
Sé que parece estúpida utilizar un if
de algo que podría ser determinado en tiempo de compilación ... pero no se preocupen, el compilador es suficientemente inteligente como para hacer figura hacia fuera en de compilación tiempo y optimizar la distancia if
y la rama sin usar por completo;)
me especializo la versión flotante en lugar de todo el flotador no uno :-) – AProgrammer
@AProgrammer, el OP sólo se menciona que quieran especializarse para TPoint, pero acuerde si quiere el segundo "conjunto" para más de una clase. –