我想在我的代码中执行一组类似的测试,但仅根据参数进行更改.
我可以用switch语句写这个:
bool doTest(EnumSensorFamily family, const StructSensorProposal& proposed)
{
switch (family)
{
case FAM1:
return (ExpectedFam1 == proposed.Fam1SensorId);
break;
case FAM2:
return (ExpectedFam2 == proposed.Fam2SensorId);
break;
case FAM3:
return (ExpectedFam3 == proposed.Fam3SensorId);
break;
default:
ERROR ("Unexpected family");
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我想用模板特化来做这件事
template <EnumSensorFamily family>
bool doTest(const StructSensorProposal& proposed);
template<>
bool doTest<FAM1> (const StructSensorProposal& proposed)
{
return (ExpectedFam1 == proposed.Fam1SensorId);
}
template<>
bool doTest<FAM2> (const StructSensorProposal& proposed)
{
return (ExpectedFam2 == proposed.Fam2SensorId);
}
template<>
bool doTest<FAM3> (const StructSensorProposal& proposed)
{
return (ExpectedFam3 == proposed.Fam3SensorId);
}
Run Code Online (Sandbox Code Playgroud)
除了避免包含几乎相同案例的switch语句之外,这样做有什么好处?
理想情况下,我希望能够编写单个方法来减少维护开销.
谢谢
建立安德鲁的答案......
请注意,EnumSensorFamily family必须在编译时知道.如果直到运行时才知道它,那么你必须写一个switch来选择模板,让你回到你开始的地方.
另一种方法是使用Traits模式:
template <EnumSensorFamily family>
struct SensorTraits;
template <>
struct SensorTraits<FAM1>
{
const EnumSensorFamily kFamilyID = ExpectedFam1;
};
template <>
struct SensorTraits<FAM2>
{
const EnumSensorFamily kFamilyID = ExpectedFam2;
};
template <>
struct SensorTraits<FAM3>
{
const EnumSensorFamily kFamilyID = ExpectedFam3;
};
template <EnumSensorFamily family>
bool doTest(const StructSensorProposal& proposed)
{
return (SensorTraits<family>::kFamilyID == proposed.Fam1SensorId);
}
Run Code Online (Sandbox Code Playgroud)
如果您尝试使用doTest缺少特征特化的传感器系列,则会出现编译错误.另请注意,您永远不会实例化traits对象,只需使用其定义即可.
这使您可以在多个函数中重用常量,typedef等.此外,添加新系列不涉及梳理所有代码以查找关注的每个switch语句.您所要做的就是创建一个新的SensorTraits专业化.
template <>
struct SensorTraits<FAM1>
{
const EnumSensorFamily kFamilyID = ExpectedFam1;
int StructSensorProposal::*proposalField = &StructSensorProposal::fam1field;
};
// ...
template <EnumSensorFamily family>
int getProposedField(const StructSensorProposal& proposed)
{
return proposed.*SensorTraits<family>::proposalField;
}
Run Code Online (Sandbox Code Playgroud)
您也可以typedef为传感器的数据类型输入:
template <>
struct SensorTraits<FAM1>
{
const EnumSensorFamily kFamilyID = ExpectedFam1;
typedef uint16_t data_type;
data_type StructSensorProposal::*proposalField = &StructSensorProposal::fam1field;
};
// ...
template <EnumSensorFamily family>
SensorTraits<family>::data_type getProposedField(const StructSensorProposal& proposed)
{
return proposed.*SensorTraits<family>::proposalField;
}
Run Code Online (Sandbox Code Playgroud)
我没有测试过这些; 你可能需要一个const或static在那里.
如果编译器无法switch正确优化(即,如果它不生成与模板解决方案相同的代码,这对于现代的内联编译器是可行的),则可以获得非常小的潜在性能提升.当然只有在family编译时常量 - 否则模板不适用,编译器可以找到的最佳优化switch是计算跳转或跳转表.
如果您的代码总是看起来像return (ExpectedFamN == proposed.FamNSensorId);,我宁愿使用数组作为期望值和传感器ID,并根据它们索引那些family.
| 归档时间: |
|
| 查看次数: |
6631 次 |
| 最近记录: |