在上节的代码中,构造函数AccT()不一定会返回一个符合条件的值,而且类型AccT也
不一定具有一个缺省的构造函数。我们可以再次使用trait来解决这个函数。
//accumtraits3.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; }; template<> class AccumulationTraits<float> { public: typedef double AccT; static AccT const zero = 0;//在类中只有整型和枚举类型的静态常量才能初始化 //static AccT const zero; //如果这样定义可以,然后在源文件进行初始化 //初始化语句为: //double const AccumulationTraits<float>::zero = 0.0; };
在上面的代码中,我们的新trait是一个常量,而常量是在编译期进行求值的,因此,
accum()现在修改如下:
//accum3.h #ifndef ACCUM_H #define ACCUM_H #include "accumtraits3.h" template<typename T> inline typename AccumulationTraits<T>::AccT accum(T const* beg,T const* end) { //返回类型是元素类型的trait typedef typename AccumulationTraits<T>::AccT AccT; AccT total = AccumulationTraits<T>::zero; while (beg != end) { total += *beg; ++beg; } return total; } #endif
然而,这种解决方案的一个缺点是:在所在类的内部,C++只允许我们对整型和枚举类型初始化
成静态成员变量。显然,对于诸如浮点型的其他类型(也包括我们自己定义的类),我们就不能
使用上面的解决方案。譬如下面的特化就是错误的:
...
template<>
class AccumulationTraits<float>
{
public:
typedef double AccT;
static double const zero = 0.0;//错误:并不是一个整形变量
};
对于这个问题,一个直接的解决方法就是不在所在类的内部定义这个value trait,如下所示:
template<>
class AccumulationTraits<float>
{
public:
typedef double AccT;
static double const zero ;
};
然后在源文件中进行初始化:
...
double const AccumulationTraits<float>::zero = 0.0;
尽管可以正常运行,但是该解决方案有一个显著的缺点:这种解决方法对编译器而言是不可知的。
也就是说,在处理客户端文件的时候,编译器通常都不会知道位于其他文件的定义。于是,在上面
这个例子中,编译器根本就不能够知道zero的值是0这个事实。
因此,我们趋向于实现下面这种value trait,而且不需要保证内联成员函数返回的必须是整型值。
我们重写改写我们的程序:
//accumtraits4.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; } }; template<> class AccumulationTraits<unsigned int> { public: typedef unsigned long AccT; static AccT zero() { return 0; } }; template<> class AccumulationTraits<float> { public: typedef double AccT; static AccT zero() { return 0; } };
对于应用程序而言,唯一的区别就是在使用的时候使用了函数调用语法
AccT total = AccumulationTraits<T>::zero();
原文链接: https://www.cnblogs.com/magic-cube/archive/2011/11/02/2233699.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/35574
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!