嵌套模板

模板可以嵌套在类/结构体或其他类/结构体模板中。联合体也是如此。

联合体一节中,我们了解了将 long 值“转换”为 double,然后再转换回来,而不会损失精度。

现在,我们可以使用模板编写一个通用的“转换器”(TemplatesConverter.mq5)。模板类 Converter 有两个参数 T1 和 T2,用于指示将在哪些类型之间执行转换。为了根据一种类型的规则写入值,并根据另一种类型的规则读取值,我们同样需要一个联合体。我们还将其制作成一个带有参数 U1 和 U2 的模板 (DataOverlay),并在类内部进行定义。

该类通过重载运算符 [] 提供了一种便捷的转换方式,在该运算符的实现中,可以对联合体字段进行写入和读取。

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

联合体用于描述类中的 DataOverlay<T1,T2>data 字段。我们可以在 DataOverlay 中直接使用 T1 和 T2,而无需将此联合体设为模板。但为了演示该技术本身,在生成 data 字段后,外部模板的参数会传递给内部模板。在 DataOverlay 内部,除了 T1 和 T2 之外,同一对类型将被称为 U1 和 U2。

我们来看看模板的实际应用。

#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
}