在上一节中所使用的trait被称为fixed trait,因为一旦定义了这个分离的trait,
就不能在算法中对它进行改写,然而,在有些情况下,我们需要对trait进行改写。
例如:我们可能偶尔发现可以对一组float值进行求和,然后很安全的把和值存储
在一个具有相同类型(即float型)的变量里面,而且这样通常会给我们带来更高
的效率。因此,我们更改我们的求和模版:
//accum5.h
#ifndef ACCUM_H
#define ACCUM_H
#include"accumtraits4.h"
template<typename T,typename AT = AccumulationTraits<T> >
class Accum
{
public:
static typename AT::AccT accum(T const *beg,T const *end)
{
typename AT::AccT total = AT::zero();
while (beg != end)
{
total += *beg;
+beg;
}
return total;
}
};
#endif
通常而言,大多数使用这个模版的用户都不必显示地提供第2个模板实参,因为我们
针对第一个实参的类型,为每种类型都配置了一个合适的缺省值。
至此,我们可以引入一个辅助模板函数来简化上面基于模板类的接口:
template<typename T>
inline
typename AccumulationTraits<T>::AccT accum(T const* beg,T const* end)
{
return Accum<T>::accum(beg,end);
}
template<typename Traits,typename T>
inline
typename Traits::AccT accum(T const* beg,T const* end)
{
return Accum<T,Traits>::accum(beg,end);
}
到目前为止,我们的程序仅仅只能进行求和操作,如果想进行求积运算怎么办?
下面我们引入policy模板,policy模板主要用来改变算法的类型,一个policy类就是
一个提供了一个接口的类,该接口能够在算法中应用一个或多个policy。
下面,为我们的Accum类模板引入policy模板:
//accum6.h
#ifndef ACCUM_H
#define ACCUM_H
#include "accumtraits4.h"
#include "sumpolicy1.h"
template<typename T,
typename Policy = SumPolicy,
typename Traits = AccumulationTraits<T> >
class Accum
{
public:
typedef typename Traits::AccT AccT;
static AccT accum(T const *beg,T const *end)
{
AccT total = Traits::zero();
while (beg != end)
{
Policy::accumulate(total,*beg);
++beg;
}
return total;
}
};
#endif
其中,SumPolicy类的代码如下:
//sumpolicy1.h
#ifndef SUMPOLICY_H
#define SUMPOLICY_H
class SumPolicy
{
public:
template<typename T1,typename T2>
static void accumulate(T1& total,T2 const & value)
{
total += value;
}
};
#endif
注:在这个例子中,我们把policy实现为一个具有一个成员函数模板的普通类,
(也就是说,类本身不是模板,而且该成员函数是隐式内联的),后面我们会实验
另一种方案。
考虑下面的程序:
#include "accum0.h"
#include <iostream>
class MultPolicy
{
public:
template<typename T1,typename T2>
static void accumulate(T1& total,T2 const & value)
{
total *= value;
}
};
int main()
{
int num[] = {1,2,3,4,5};
//输出所有值的乘积
std::cout << "The MultPolicy result is :" << Accum<int,MultPolicy>::accum(&num[0],&num[5]) << std::endl;
return 0;
}
然后,程序的结果是:
The MutlPolicy result is : 0
这说明,不同的trait和不同的policy应该是互相交互的,我们应该以更加细心的态度来对待模板设计。