我有一个包含 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 多种数据类型,如果我将它们全部列在开关大小写中,维护起来就太复杂了。
我想知道是否有更好的方法来处理这种情况?我的项目使用的是 C++98,还没有升级到 C++11。谢谢。
问候燕华
你的这段代码将强制编译器实现你的类的 100 个或更多变体,而不会提高性能或可读性。如果你问我,这简直太疯狂了。
有人可能想知道为什么你首先需要动态实例化,但你肯定有一个很好的理由......
您可以对数据使用双精度,如果您需要完美的整数精度,则可以对整数值进行专用化。
然后,您可以存储数据类型,假设您需要一些特定的处理,例如根据原始类型显示数字,这甚至可能不是必需的。
忘记C++魔术消除你的设计问题,这是我的建议。这种语言即使经过精心设计也能产生怪物,如果你故意要求它,那就更是如此。
编辑
自从您的评论以来,我不知道这是用于运行时的,因此下面的解决方案对您不起作用。(但我在这里让它激发你进行不同的实现。
你必须知道一些事情:模板是在编译时计算的,因此不是一个有效的工具,因为你试图在运行时计算类型。
您将需要定义每种可能性。
已弃用的答案
解决方案 1
在这种情况下,您为什么不只使用using
关键字?
using DATA_TYPE_FLOAT = float;
using DATA_TYPE_INT32 = int;
const auto my_c = MyClass<DATA_TYPE_INT32, DATA_TYPE_FLOAT>();
解决方案 2
更改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;
}