[转]C++模板元编程——Traits
通过一个计算序列元素的累加和的小函数来说明traits的使用。
计算一个序列的累加和:
template<typename T>
T accum(const T* beg, const T* end)
{
T total = T();
while(beg != end)
{
total += *beg;
++beg;
}
return total;
}
使用accum:
int a[] = {3, 5, 7, 9};
const char* str = "abcd";
cout << "the a average: " << accum(a,a + 4) / 4 << endl;
cout << "the str average: " << accum(str,str + 4) / 4 << endl;
输出结果:
the a average: 6
the str average: -29
问题来了,"abcd" 串的平均值居然是-29, 这明显是不对的。问题出在T total,total 的类型为char,导致total += *beg 溢出。
解决的办法是通过类型T,得到一个比T能够表达更大范围的类型T1, 尽可能的保证不溢出。
1 特征类(traits)
定义AccumTraits特征类:
template<typename T>
struct AccumTraits
{
typedef T type; //默认情况下AccumTraits<T>::type 即为T
};
AccumTraits特征类char类型的特化:
template<>
struct AccumTraits<char>
{
typedef int type; // //AccumTraits<char>::type 即为int
};
AccumTraits特征类int类型的特化:
template<>
struct AccumTraits<int>
{
typedef long type;
};
应该特化各种常用的容易溢出的类型如:char、short、int、float,以及相应的unsigned char、unsigned short ...
重新实现accum模板函数:
template<typename T>
typename AccumTraits<T>::type
accum(const T* beg, const T* end)
{
typename AccumTraits<T>::type total = AccumTraits<T>::type();
while(beg != end)
{
total += *beg;
++beg;
}
return total;
}
再次使用该函数:
int a[] = {3, 5, 7, 9};
const char* str = "abcd";
cout << "the a average: " << accum(a,a + 4) / 4 << endl;
cout << "the str average: " << accum(str,str + 4) / 4 << endl;
输出结果:
the a average: 6
the str average: 98