我有一个包含2个类型参数的模板类。当我创建类实例时,我需要检查2个其他枚举值来决定这个类类型参数。
enum DataType_t
{
DATA_TYPE_INT32 = 1,
DATA_TYPE_FLOAT = 2,
DATA_TYPE_DOUBLE = 3
// totally more then 10 type enum value,
};
class MyClassBase
{};
template<typename InputDataType, typename OutputDataType>
class MyClass:public MyClassBase
{
private:
InputDataType inputData;
OutputDataType outputData;
public:
MyClass() {};
~MyClass() {};
};
MyClassBase* make_instance(DataType_t inputDataType, DataType_t outputDataType)
{
switch (inputDataType)
{
case DATA_TYPE_INT32:
switch (outputDataType)
{
case DATA_TYPE_INT32:
return new MyClass<int, int>();
case DATA_TYPE_FLOAT:
return new MyClass<int, float>();
case DATA_TYPE_DOUBLE:
return new MyClass<int, double>();
}
break;
case DATA_TYPE_FLOAT:
switch (outputDataType)
{
case DATA_TYPE_INT32:
return new MyClass<float, int>();
case DATA_TYPE_FLOAT:
return new MyClass<float, float>();
case DATA_TYPE_DOUBLE:
return new MyClass<float, double>();
}
break;
case DATA_TYPE_DOUBLE:
switch (outputDataType)
{
case DATA_TYPE_INT32:
return new MyClass<double, int>();
case DATA_TYPE_FLOAT:
return new MyClass<double, float>();
case DATA_TYPE_DOUBLE:
return new MyClass<double, double>();
}
break;
default:
break;
}
return NULL;
}
我可以像上面那样编写make_instance
函数,但我觉得这不是一种优雅的方式。实际上,枚举DataType_t
定义了10种以上的数据类型,如果我将它们全部列在switch case中,那么维护起来就太复杂了。
我想知道是否有更好的方法来处理这种情况?我的项目是使用C ++ 98,而不是升级到C ++ 11.谢谢。
此致 燕化
答案 0 :(得分:0)
您的此代码将强制编译器实现您的类的100个或更多变体,因为性能或可读性没有任何好处。如果你问我,这很简单。
有人可能想知道为什么你首先需要动态的实例化,但你肯定有一个很好的理由......
您可以使用双精度数据,如果需要完美的整数精度,可以对整数值进行专门化。
然后你可以存储数据类型,假设你需要一些特定的处理,比如根据原始类型显示数字,甚至可能不需要。
忘记C ++将你的设计问题驱逐出去,这是我的建议。这种语言即使经过精心设计也能产生monstruosities,如果你故意要求它,那就更是如此。
答案 1 :(得分:0)
我不知道你的评论是否适合运行时,所以下面的解决方案对你不起作用。 (但我在这里说的是它激发了你对不同实现的启发。
你必须知道一些事情:模板被评估为COMPILE时间,因此你不是一个有效的工具,因为你试图在RUNTIME评估类型。
您需要定义每种可能性。
在此案例中,为什么不使用using
关键字?
using DATA_TYPE_FLOAT = float;
using DATA_TYPE_INT32 = int;
const auto my_c = MyClass<DATA_TYPE_INT32, DATA_TYPE_FLOAT>();
更改make_
功能的用途。就像STL一样,你应该构建你的对象传递参数,这些参数将由MyClass
保存。在你的情况下,你做错了。这是我的解决方案:
#include <type_traits>
template <typename I, typename O>
class MyClass {
private:
I input;
O output;
public:
MyClass(const I& new_input, const O& new_output)
: input(new_input), output(new_output) {}
};
template <typename I, typename O>
auto make_instance(I input, O output) -> MyClass<typename std::decay<I>::type, typename std::decay<O>::type> {
return MyClass<typename std::decay<I>::type, typename std::decay<O>::type>(input, output);
}
int main() {
const auto c = make_instance(4, 3.2);
return 0;
}