设计一个模板函数,用来求和。并且用Traits机制一步一步完善:
//traits/accum1.h
#ifndef ACCUM_H
#define ACCUM_H
template <typename T>
inline
T accum(T const* beg, T const* end)
{
T total = T();
while(beg != end){
total +=*beg;
++beg;
}
return total;
}
#endif //ACCUM_H
#include "stdafx.h"
#include "accum1.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int num[] = {1,2,3,4,5};
cout<<"the average value of the integer values is "
<<accum(&num[0], &num[5])/5<<endl;
char name[] = "templates";
int length = sizeof(name)-1;
cout<<"the average value of the characters in /""
<< name<<"/" is "
<<accum(&name[0],&name[length])/length<<endl;
return 0;
}
仔细分析以上代码,会发现一个问题,首先 对于Char 而言,main函数会输出错误的结果,因为char的位数有限,所以导致求出的平均值有误(数组之和大于255,导致平均值为-5),其次 T total = T();并不能满足任意类型。
于是我们利用Traits机制邦定T的特征。
//accumtraits2.h
template<typename T>
class AccumulationTraits;
template<>
class AccumulationTraits<char>{
public:
typedef int AccT;
static AccT const zero = 0;
};
template<>
class AccumulationTraits<short>{
public:
typedef int AccT;
static AccT const zero = 0;
};
template<>
class AccumulationTraits<int>{
public:
typedef long AccT;
static AccT const zero = 0;
};
//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 typename AccumulationTraits<T>::AccT AccT;
AccT total = AccumulationTraits<T>::zero;
while(beg != end){
total +=*beg;
++beg;
}
return total;
}
#endif //ACCUM_H
以上代码可以解决上述提到的两个问题。但是针对
template<>
class AccumulationTraits<float>{
public:
typedef double AccT;
static AccT const zero = 0.0;//错误,C++只允许我们对整型和枚举类型初始化成静态成员变量。
};
可重新实现如下
template<>
class AccumulationTraits<float>{
public:
typedef double AccT;
static AccT const zero;//这里只有声明};
将初始化写在源文件中
double const AccmulatinTraits<float>::zero = 0.0;
但新的问题又来了:这种解决方案对编译器而言是不可知的。
于是我们又得到了下面新的解决方案:
//accumtraits3.h
template<typename T>
class AccumulationTraits;
template<>
class AccumulationTraits<char>{
public:
typedef int AccT;
static AccT zero(){
return 0;
}
};
template<>
class AccumulationTraits<short>{
public:
typedef int AccT;
static AccT zero(){
return 0;
}
};
template<>
class AccumulationTraits<int>{
public:
typedef long AccT;
static AccT zero(){
return 0;
}
};
//accum3.h
#include "accumtraits3.h"
template<typename T>
inline
typename AccumulationTraits<T>::AccT accum(T const* beg, T const* end)
{
typedef typename AccumulationTraits<T>::AccT AccT;
AccT total = AccumulationTraits<T>::zero();
while(beg != end){
total +=*beg;
++beg;
}
return total;
}