Plantillas anidadas

Las plantillas pueden anidarse dentro de clases/estructuras o dentro de otras plantillas de clases/estructuras. Lo mismo ocurre con las uniones.

En la sección Uniones vimos la posibilidad de «convertir» los valores long en double y viceversa sin pérdida de precisión.

Ahora podemos utilizar plantillas para escribir un «conversor» universal (TemplatesConverter.mq5). La clase de plantilla Converter tiene dos parámetros T1 y T2 que indican los tipos entre los que se realizará la conversión. Para escribir un valor según las reglas de un tipo y leerlo según las reglas de otro necesitamos de nuevo una unión. Lo convertiremos también en una plantilla (DataOverlay) con los parámetros U1 y U2, y lo definiremos dentro de la clase.

La clase proporciona una práctica transformación sobrecargando los operadores [], en cuya implementación se escriben y leen los campos de unión.

template<typename T1,typename T2>
class Converter
{
private:
   template<typename U1,typename U2>
   union DataOverlay
   {
      U1 L;
      U2 D;
   };
   
   DataOverlay<T1,T2data;
   
public:
   T2 operator[](const T1 L)
   {
      data.L = L;
      return data.D;
   }
   
   T1 operator[](const T2 D)
   {
      data.D = D;
      return data.L;
   }
};

La unión se utiliza para describir el campo DataOverlay<T1,T2>data de dentro de la clase. Podríamos utilizar T1 y T2 directamente en DataOverlay y no hacer de esta unión una plantilla, pero para demostrar la técnica en sí, los parámetros de la plantilla externa se pasan a la plantilla interna cuando se genera el campo data. Dentro de DataOverlay, el mismo par de tipos se conocerá como U1 y U2 (además de T1 y T2).

Veamos la plantilla en acción.

#define MAX_LONG_IN_DOUBLE       9007199254740992
   
void OnStart()
{
   Converter<double,ulongc;
   
   const ulong value = MAX_LONG_IN_DOUBLE + 1;
   
   double d = value// possible loss of data due to type conversion
   ulong result = d// possible loss of data due to type conversion
   
   Print(value == result); // false
   
   double z = c[value];
   ulong restored = c[z];
   
   Print(value == restored); // true
}