template<typename T>
T Accum(const T* pBegin, const T* pEnd)
{
T total = T();
while(pBegin != pEnd)
{
total += *pBegin;
++pBegin;
}
return total;
}
1、返回值trait
如果T为char时,返回值也为char将会有问题,如a+b+c将会很快就到z,实际想要的应该是返回int
template<typename T>
class Train
{
public:
typedef Ret T; // 默认使用T即可
}
//特例化1
template<>
class Train<char>
{
pulibc:
typedef int Ret;
}
使用
template<typename T>
typename Train<T>::Ret Accum(const T* pBegin, const T* pEnd)
{
typedef typename Train<T>::Ret Ret;
Ret total = Ret();
}
也可以使用宏定义,能够精简代码,实现更多的特例化
#define MK_RETURN(T1, T2) \
template<>
class Train<T1>
{
typedef T2 Ret;
};
使用
MK_RETURN(int, long)
....
2、值的trait
前面默认使用T()来赋值初始化,而有些时候T()并不一定就满足需求了,我们可以对值进行特性处理
template<typename T>
class Train
{
public:
typedef Ret T; // 默认使用T即可
static Ret zero()
{
return T();
}
}
实例化
template<>
class Train<char>
{
pulibc:
typedef int Ret;
static Ret zero()
{
return 1; //默认赋值为1
}
}
使用
template<typename T>
typename Train<T>::Ret Accum(const T* pBegin, const T* pEnd)
{
Ret Total = Train<T>::zero();
}
3、参数的trait
上述两种train都称为fix trait,因为一旦定义了这个分离的trait,就不能在算法中对它进行改写。
template<typename T, typename traits= Train<T> >
class Accum
{
public:
static typename traits::Ret accum(const T* pBegin, const T* pEnd)
{
typename traits::Ret total = traits::Zero();
...
}
}
可以由用户指定,如果觉得int,返回值int也够用的话。可以使用
Accum<int, Train<int> >::accum(...); 即可
4、policy
前面例子中一直使用的是+=,如果觉得这个算法也可以实例化,我们称之为policy,policy更加强调动作,算法,trait更加强调名词,类型。
template<typename T,typename Policy = SumPolicy, typename traits= Train<T> >
class Accum
{
public:
typedef typename traits::Ret Acct;
static Acct accum(const T* pBegin, const T* pEnd)
{
Acct total = traits::Zero();
while(pbegin != pEnd)
{
Policy::accumulate(total, *pBegin);
++pBegin;
}
}
}
具体实例化
class Sumplicy
{
public:
template<typename T1, typename T2>
static void accumulate(T1& total, const T2& value)
{
total += value;
//我们也可以实例化为其它操作,如
total *= value;
}
}