成员模版和模版的模板参数
之前我们为了实现一个累积的policy,我们选择把SumPolicy和MutPolicy实现为具有成员模版的普通类,这里,还存在另一种实现方法,即使用类模板来实现这个policy class接口:
#ifndef SUMPOLICY_H
#define SUMPOLICY_H
template<typename T1,typename T2>
class SumPolicy
{
public:
static void accumulate(T1& total,T2 const & value)
{
total += value;
}
};
#endif
我们对累积求和类Accum的接口进行修改,从而使用一个模板的模板参数,代码如下:
#ifndef ACCUM_H
#define ACCUM_H
#include "accumtraits4.h"
#include "sumpolicy2.h"
template<typename T,
template<typename,typename> class 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<AccT,T>::accumulate(total,*beg);
++beg;
}
return total;
}
};
实际上也可以对trait参数应用这种相同的转化。
通过模板的模板参数访问policy class的主要优点在于:借助于某个依赖于模板参数的类型,就很容易让policy class携带一些状态信息(也就是静态成员变量)。而在之前的解决方案中,却不得不把静态成员变量嵌入到成员类模板中。然而,这种模板的模板参数也存在一个缺点:policy类现在必须被写成模板,而且我们的接口中还定义了模板参数的确切个数。遗憾的是,这个定义会让我们无法在policy中添加额外的模板参数。例如:我们希望给SumPolicy添加一个Boolean型的非类型模板实参,从而可以选择是用+=运算符来进行求和,还是只用+运算符来进行求和。如果我们不使用模板的模板参数,我们只需这样改动SumPolicy模板即可:
#ifndef SUMPOLICY_H
#define SUMPOLICY_H
template<bool use_compound_op = true>
class SumPolicy
{
public:
template<typename T1, typename T2>
static void accumulate(T1& total,T2 const & value)
{
total += value;
}
};
template<>
class SumPolicy<false>
{
public:
template<typename T1,typename T2>
static void accumulate(T1& total,T2 const & value)
{
total = total + value;
}
};
#endif
然而,如果我们使用模板的模板参数来实现上面的Accum,那么将不能做这样的修改。
下面,我们运用普通的迭代器进行累积
#ifndef ACCUM_H
#define ACCUM_H
#include <iterator>
#include "accumtraits4.h"
template<typename Iter>
inline
typename std::iterator_traits<Iter>::value_type
accum(Iter start,Iter end)
{
typedef typename std::iterator_traits<Iter>::value_type VT;
VT total = VT();
while (start != end)
{
total += *start;
++start;
}
return total;
}
#endif
其中,iterator_traits是C++标准库提供的trait(可以看出,到处都是trait)。该结构封装了迭代器的所有相关属性。由于存在一个适合指针的局部特化,所以普通指针类型也能使用这些trait。下面的(不完整的)例子展示了:标准库如何实现和如何提供这些支持的:
namespace std{
template <typename T>
struct iterator_traits<T*>{
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
typedef T* pointer;
typedef T& reference;
};
}

浙公网安备 33010602011771号