1、最简单的情况:
template<class T>
T Add(const T& a, const T& b)
{
return a + b;
}
缺点是不能够处理不同类型的数据,例如Add(100, 100.0f);
2、第二种情况:
template<typename T1, typename T2>
T1 Add1(T1 lhs, T2 rhs)
{
return lhs + rhs;
}
这种情况下,能够处理不同类型的数据,但是有些情况下有些数据精度会丢失,例如:Add(100, 100.1f)
3、第三种情况:
这种是根据第二种情况的改良,因为第二种会丢失数据精度主要是因为无法判断两个数据类型的精度,从而确定返回值的类型,利用模板trait技巧,我们可以实现。
在写代码之前我们需要先了解typename作用:(1)标识一个模板参数类型(2)表示后面一个是一个类型名
template<bool T,class T1,class T2>
class ReturnTypeFun;
template<class T1,class T2>
class ReturnTypeFun<true,T1,T2>
{
public:
typedef T1 ReturnType;
};
template<class T1, class T2>
class ReturnTypeFun<false, T1, T2>
{
public:
typedef T2 ReturnType;
};
template<typename T1,typename T2>
class ReturnValueType
{
public:
//注意:此处sizeof比较大小需要加括号
typedef typename ReturnTypeFun<(sizeof(T1) > sizeof(T2)), T1, T2 > ::ReturnType ReturnType;
};
//因为int和float类型所占的字节相同,所以无法通过比较大小来判断类型的精度,需要偏特化
template<>
class ReturnValueType<int, float>
{
public:
typedef float ReturnType;
};
template<>
class ReturnValueType<float, int>
{
public:
typedef float ReturnType;
};
template<class T1,class T2>
typename ReturnValueType<T1, T2>::ReturnType Add(T1 left, T2 right)
{
return left + right;
}
T::iterator这种名称,由于iterator具体是类型还是成员变量取决于T的类型实现,所以当我们知道T::iterator是个类型名称时,如果我们要使用这个类型名,前面必须要加typename.