泛型编程之特性(traits)
特性(traits):对于某种可能会出错的返回值型别(Return Type),利用类模版进行部分特例化。其思想类似设计模式。
我们只能部分特例化类模板,而不能部分特例化函数模版。——《C++ Primer(5th)》 P628
part 1. 实现 Sigma 函数
功能:将一段范围内的元素求累加和。
1. 错误的代码实例:
template <typename T> T sigma(T* start, T* end) { T total = T(); while (start != end) total += *start++; return total; }
1.1 错误原因:
如果传入 char 类型范围(迭代器)“a b c”,理论上计算结果应该返回 294 ,也就是 0x0126 ,存储需要两个字节。但是 char 只有一个字节大小,所以会造成溢出。
实际输出结果为 38 ——也就是溢出之后的值。
2. 正确的代码,采用偏特化,针对不同的型别写出不同的对策——本例中“对策”是声明不同的内置型别来存储返回值类型。
template <typename T> class SigmaTraits {}; template<> class SigmaTraits <char> // 针对char型的对策 { public: typedef int returnType; }; template<> class SigmaTraits <int> // 针对int型的对策 { public: typedef int returnType; }; template <typename T> typename SigmaTraits<T>::returnType sigma(T* start, T* end) { typedef typename SigmaTraits<T>::returnType returnType; returnType total = returnType(); while (start != end) { total += *start++; } return total; }
3. 调用 sigma 函数的方法方式都是一样的。
3.1 char范围的调用实例:
char str[] = "abc"; cout << sigma(str, str + 3) << endl;
3.2 int范围的调用实例:
int arr[] = {1, 2, 3}; cout << sigma(arr, arr+3) << endl;
4. 总结
理解 traits 更像像是一种设计模式,类似于工厂方法:针对不同的型别,有不同的对策。
模版类 SigmaTraits 叫做 traits template,它含有其参数型别 T 的一个特性(trait),即 ReturnType。
智慧在街市上呼喊,在宽阔处发声。