成员模版和模版的模板参数

之前我们为了实现一个累积的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;
	};
}

 


posted @ 2011-11-07 19:16  MagiCube  阅读(2339)  评论(0编辑  收藏  举报