【发布时间】:2014-06-19 06:17:58
【问题描述】:
我的一个项目中有很多自定义数据类型,它们都共享一个公共基类。
我的数据(来自数据库)的数据类型由基类的枚举来区分。我的架构允许使用派生类专门化特定的数据类型,或者它可以由基类处理。
当我构造一个特定的数据类型时,我通常会直接调用构造函数:
Special_Type_X a = Special_Type_X("34.34:fdfh-78");
a.getFoo();
有一些模板魔法也允许像这样构造它:
Type_Helper<Base_Type::special_type_x>::Type a = Base_Type::construct<Base_Type::special_type_x>("34.34:fdfh-78");
a.getFoo();
对于枚举类型的某些值,可能没有专门化,所以
Type_Helper<Base_Type::non_specialized_type_1>::Type == Base_Type
当我从数据库中获取数据时,数据类型在编译时是未知的,因此有第三种方法来构造数据类型(来自 QVariant):
Base_Type a = Base_Type::construct(Base_type::whatever,"12.23@34io{3,3}");
但我当然希望调用正确的构造函数,所以该方法的实现过去看起来像:
switch(t) {
case Base_Type::special_type_x:
return Base_Type::construct<Base_Type::special_type_x>(var);
case Base_Type::non_specialized_type_1:
return Base_Type::construct<Base_Type::non_specialized_type_1>(var);
case Base_Type::whatever:
return Base_Type::construct<Base_Type::whatever>(var);
//.....
}
这段代码是重复的,因为基类也可以处理新类型(添加到枚举中),所以我想出了以下解决方案:
// Helper Template Method
template <Base_Type::type_enum bt_itr>
Base_Type construct_switch(const Base_Type::type_enum& bt, const QVariant& v)
{
if(bt_itr==bt)
return Base_Type::construct<bt_itr>(v);
return construct_switch<(Base_Type::type_enum)(bt_itr+1)>(bt,v);
}
// Specialization for the last available (dummy type): num_types
template <>
Base_Type construct_switch<Base_Type::num_types>(const Base_Type::type_enum& bt, const QVariant&)
{
qWarning() << "Type" << bt << "could not be constructed";
return Base_Type(); // Creates an invalid Custom Type
}
我原来的switch语句被替换为:
return construct_switch<(Base_Type::type_enum)0>(t,var);
此解决方案按预期工作。
但是编译后的代码是不同的。虽然原始 switch 语句的复杂度为 O(1),但新方法的复杂度为 O(n)。生成的代码递归调用我的辅助方法,直到找到正确的条目。
为什么编译器不能正确优化这个?有没有更好的方法来解决这个问题?
类似的问题: Replacing switch statements when interfacing between templated and non-templated code
【问题讨论】:
标签: c++ templates template-meta-programming