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

Correct way of determening the template type of variable in C++

本文关键字:方法 类型 C++ 变量 确定      更新时间:2023-10-16

请考虑以下事项:

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(type) 进行比较是一个坏主意,为什么?

其次,是否有一个设计模型可以涵盖这样的案例?

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

在这种情况下,我相信是的。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)。