value trait

在上节的代码中,构造函数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();

你可能感兴趣的:(value)