是否可以推导出模板模板参数参数没有错字:-)

问题描述

我有一个类为一个巨大的项目实现数据类型。我这里简化为(其实就是一个子类把typeID和subTypeID传递给iots父类构造函数):

template<typename T,uint32_t typeID,uint32_t subTypeID> class TDataType {
  private:
    T _value;
};

请注意,在这种情况下,不能使用类似于变体的内容。还需要类型 ID,这与 OO 无关,而与软件配置有关。我确实将它们包含在这个简单示例中只是为了显示完整的模板参数。

我想要实现的是实现一个能够透明地从一种简单类型转换为另一种类型的转换模板(对于某些类型(如 std::string),我知道我需要一个专门的模板。

所以我想要这样的东西(伪语法)将 T1 转换为 T2 都是一些 TDataType 类:

template<class TDataType<typename T1,uint32_t TYP1,uint32_t STYP1>,class TDataType<typename T2,uint32_t TYP2,uint32_t STYP2>> convert(TDataType<T1,TYP1,STYP1> &v1,TDataType<T2,TYP2,STYP2> &v2)
          { v1._value = static_cast<T1>(v2._value); }

从传递的 TDataType 推导出 T1/2、TYP1/2 和 STYP1/2

例如,可以执行以下操作:

TDataType<int32_t,1,32> Int{3};
TDataType<double,2,2> Double;

convert(Int,Double); // Set Double to 3.0

请注意,thios 转换只是用例的一个示例,例如还有更多类似的操作符。所以我主要看这个模板-模板-参数-参数推导是否可以。

一个例子是:

template<class TDataType<typename T,uint32_t TYP,uint32_t STYP>,typename LT> 
    operator=(LT &lh,TDataType<T,TYP,STYP> &rh) 
      { lh = static_cast<LT>(rh._value); }

将 TDataType 简单地分配给另一个 TDataType 不是问题,因为这可以在目标类模板内部实现,并使用 static_cast 的“本地”模板类型参数。

解决方法

当然有可能,正确的语法很简单:

template<typename T1,uint32_t TYP1,uint32_t STYP1,typename T2,uint32_t TYP2,uint32_t STYP2>
void convert(TDataType<T1,TYP1,STYP1> from,TDataType<T2,TYP2,STYP2> &to)
{
    to = static_cast<T2>(from.value()); // assuming TDataType has a ctor TDataType(T)
}

但是创建一个直接从另一个 TDataType 实例初始化的模板化转换构造函数可能会更好:

template<typename T,uint32_t typeID,uint32_t subTypeID>
class TDataType {
    T _value;
public:
    TDataType(T value) : _value(value) {}

    template<typename P,uint32_t pTypeID,uint32_t pSubTypeID>
    TDataType(TDataType<P,pTypeID,pSubTypeID> that) : _value(static_cast<T>(that._value)) {}

    template<typename,uint32_t,uint32_t>
    friend class TDataType; // to be able to access that._value
};

或者,使用用户定义的转换运算符使不同的 TDataType 可以相互转换。

template<typename T,uint32_t pSubTypeID>
    operator TDataType<P,pSubTypeID>() const {
        return static_cast<P>(_value);
    }
};

您可以进一步特化转换运算符以根据目标类型执行不同的操作和/或声明默认特化为已删除以更好地控制允许哪些转换。

然后你就可以:

TDataType<int32_t,1,32> Int{ 3 };
TDataType<double,2,2> Double = Int;