在C ++中确定变量模板类型的正确方法

时间:2015-01-14 02:45:52

标签: c++ rtti

请考虑以下事项:

class fooBase{
public:
       enum dataType {fooInt, fooFloat, fooInvalid};
       fooBase(){}

       /* void getLocation .. setLocation .. */

       virtual dataType getDataType() = 0;

private:
       int fooDataLocation;
};

template <typename T> class fooDataPoint : public fooBase{
public:
       fooDataPoint(T foodat) :
       fooData(foodat){}

       dataType getDataType(){
                if(typeid(float) == typeid(T))
                return fooFloat;
                if(typeid(int) == typeid(T))
                return fooInt
                return fooInvalid;
       }


private:
        T fooData;
};

template <typename T> class calculatableFooDataPoint : public fooBase{
public:
       fooDataPoint(T foodat, T bardat) :
       fooData(foodat){}

       dataType getDataType(){
                if(typeid(float) == typeid(T))
                return fooFloat;
                if(typeid(int) == typeid(T))
                return fooInt
                return fooInvalid;
       }

       void doCalculation(){
                foodata *= barData;
       }

       /* .. getData .. */
private:
        T fooData;
        T barData;
};

std::vector<foobase *> fooVector;

这将使我能够在向量中存储不同类型的数据。然后,当我需要强制转换时,而不是通过无穷无尽的dynamic_case<class<type> *>(pointer)列表,我可以先检查数据类型,然后再转换为正确的类类型。

同样在序列化和反序列化数据点时(我只需要保存结构,而不是已经处理的实际数据),我可以使用getDataType来确定类型并编写它的序列化形式。

我想我的底线是,使用typeid(类型)比较一个坏主意,为什么?

其次,是否有可以涵盖此类案例的设计模型?

1 个答案:

答案 0 :(得分:1)

  

我想我的底线是,使用typeid(类型)比较一个坏主意,为什么?

在这种情况下,我相信它是。 T的类型在编译时是已知的,因此没有理由通过一系列if来确定您已经知道的内容。你可以为此编写一个简单的元函数。此外,不需要使用动态分派来确定函数的类型,您可以将值存储在基数中:

class fooBase {
    enum dataType { fooInt, fooFloat, … };
    const dataType type;
    fooBase(dataType t) : type(t) {}
    …
    dataType getDataType() const { return type; }
};

template <typename T>
struct DataType;
template <> struct DataType<int>   
   { static const dataType value = fooBase::fooInt; };
template <> struct DataType<float> 
   { static const dataType value = fooBase::fooFloat; };

然后dataPoint的构造函数将是:

template <typename T>
fooDataPoint<T>::fooDataPoint(T data) 
: fooBase(DataType<T>::value) 
, fooData(data)
{}

除此之外,设计对于可扩展性并不是那么好,因为需要为您可能想要包含的任何类型T更新基础(扩展枚举),但如果该集合是提前知道这可能不会造成太多负担。

如果选项的数量有限,对象的大小不是太大,你可以使用像boost::variant这样的预建解决方案,它的优势在于它不会需要动态分配,它不会强制层次结构。潜在的缺点是,作为一个有区别的联合,每个对象的大小大约是它所拥有的最大类型的大小(sizeof)。