C++中确定变量模板类型的正确方法
Correct way of determening the template type of variable in C++
考虑以下几点:
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;
这将使我能够在向量中存储不同类型的数据。然后,当我需要转换时,我可以先检查数据类型,然后转换为正确的 class 类型,而不是遍历无穷无尽的 dynamic_case<class<type> *>(pointer)
列表。
同样在序列化和反序列化数据点时(我只需要保存结构,而不是已处理的实际数据),我可以只使用 getDataType 来确定类型并编写它的序列化形式。
我想我的底线是,使用 typeid(type) 进行比较是个坏主意,为什么?
其次,是否有设计模型可以涵盖这样的案例?
I guess my bottom line is, is using typeid(type) for comparision a bad idea, and why?
在这种情况下,我相信是的。 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
更新基础(扩展枚举),但是如果set 是预先知道的,这可能不是太大的负担。
如果选项数量有限,和对象的大小相差不大,您可以使用像boost::variant
这样的预建解决方案,它具有优点是它不需要动态分配并且不强制层次结构。潜在的缺点是,作为一个有区别的联合,每个对象的大小大约是它所拥有的最大类型的大小(sizeof
)。
考虑以下几点:
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;
这将使我能够在向量中存储不同类型的数据。然后,当我需要转换时,我可以先检查数据类型,然后转换为正确的 class 类型,而不是遍历无穷无尽的 dynamic_case<class<type> *>(pointer)
列表。
同样在序列化和反序列化数据点时(我只需要保存结构,而不是已处理的实际数据),我可以只使用 getDataType 来确定类型并编写它的序列化形式。
我想我的底线是,使用 typeid(type) 进行比较是个坏主意,为什么?
其次,是否有设计模型可以涵盖这样的案例?
I guess my bottom line is, is using typeid(type) for comparision a bad idea, and why?
在这种情况下,我相信是的。 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
更新基础(扩展枚举),但是如果set 是预先知道的,这可能不是太大的负担。
如果选项数量有限,和对象的大小相差不大,您可以使用像boost::variant
这样的预建解决方案,它具有优点是它不需要动态分配并且不强制层次结构。潜在的缺点是,作为一个有区别的联合,每个对象的大小大约是它所拥有的最大类型的大小(sizeof
)。