要求:编写一个能适合许多类型的模板来完成一个累加操作
解答1:
//定义一个模板函数
#ifndef ACCUM_H
#define ACCUM_H
template<typename T>
inline
T accum(T const* beg,T const* end)
{
T total=T();//假设T()事实上会产生一个等于0的值
while(beg != end)
{
total += *beg;
++beg;
}
return total;
}
#endif
解析:上面的代码,有两个问题:
(1)如何正确生成一个0值,以便开展我们的求和过程。
(2)如何确保T类型相加的和不会溢出。
比如:
我们在下面的源文件中调用上述代码:
#include"accum0.h"
#include<iostream>
int main()
{
int num[] = {1,2,3,4,5};
char name[] = "templates";
int length = sizeof(name)-1;
std::cout << "The average value of the integer values is :"
<< accum(&num[0],&num[5])/5 << std::endl;
std::cout << "The average value of the characters in \" "
<< name << "\" is: "
<< accum(&name[0],&name[length])/length
<< std::endl;
return 0;
}
代码产生的结果为:
The average value of the integer values is :3
The average value of the characters in “templates” is :-5
我们发现当我们使用字符char类型的时候,就发生了求和溢出的现象。
显然,我们可以通过引入一个额外的模板参数AccT来解决这个问题,其中
AccT描述了变量total的类型,然而这样会给该模板的使用者都强加了一个
额外的负担,他们每次在调用这个模板的时候,都要指定这个额外的类型,
我们每次不得不这样来写:
accum<int>(&nume[0],&name[length])
虽说这个约束不是很麻烦,但是我们仍然希望避免这个约束。
此时,我们引入trait模板,其中定义的是和类型T的一些关联特征。
//accumtraits2.h
template<typename T>
class AccumulationTraits;
template<>
class AccumulationTraits<char>{
public:
typedef int AccT;
};
template<>
class AccumulationTraits<short>{
public:
typedef int AccT;
};
template<>
class AccumulationTraits<int>{
public:
typedef long AccT;
};
template<>
class AccumulationTraits<unsigned int>{
public:
typedef unsigned long AccT;
};
template<>
class AccumulationTraits<float>{
public:
typedef double AccT;
};
在上面的代码中,模板AccumulationTraits被称为一个trait模板,因为
它含有它的参数类型的一个trait。
现在,我们可以改写前面写的accum()模板了:
//accum2.h
#ifndef ACCUM_H
#define ACCUM_H
#include "accumtraits2.h"
template<typename T>
inline
typename AccumulationTraits<T>::AccT accum(T const* beg,T const* end)
{
typedef AccumulationTraits<T>::AccT AccT;
AccT total = AccT();
while(beg != end)
{
total += *beg;
++beg;
}
return total;
}
#endif
现在我们运行前面的程序,就会出现我们期望的结果:
The average value of the integer values is :3
The average value of the characters in “templates” is :108