使用模板而不是开关 [英] Using template instead of switch

查看:113
本文介绍了使用模板而不是开关的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的代码中执行一组类似的测试,但只根据一个参数改变。

I want to perform a set of tests in my code that are similar but change only depending on a parameter.

我可以使用switch语句写: / p>

I could write this using a switch statement:

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;
  }
}



我想要用模板专门化p>

I was thinking of doing this with template specialisations

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);
}

除了避免switch语句包含near

Is there any benefit of doing this apart from avoiding a switch statement containing near identical cases?

我希望能够编写单一方法以减少维护开销。

Ideally I would like to be able to write single method to reduce the maintenance overhead.

推荐答案

建立安德鲁的回答...

Building off Andrew's answer...

EnumSensorFamily family 必须在编译时已知。如果直到运行时才知道,那么你必须写一个开关来选择模板,让你回到你开始的地方。

Note that the EnumSensorFamily family must be known at compile time. If it is not known until run time, then you'll have to write a switch to choose the template, putting you back where you started.

另一种方法是使用Traits模式:

Another way to do this is with the Traits pattern:

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);
}

如果您尝试使用 doTest 与缺乏traits专业化的传感器家族,你得到一个编译错误。还要注意,你永远不会实例化一个traits对象,你只需使用它的定义。

If you try to use doTest with a sensor family that lacks a traits specialization, you get a compile error. Also note that you never instantiate a traits object, you just use its definitions.

这允许你重复使用常量,typedef,无论在几个函数。此外,添加一个新的家庭不涉及梳理所有的代码,寻找每个开关关心的语句。您需要做的是创建一个新的 SensorTraits 专业化。

This lets you reuse constants, typedefs, whatever in several functions. Additionally, adding a new family does not involve combing through all the code looking for every switch statement that cares. All you have to do is create a new SensorTraits specialization.

编辑:可以使该字段依赖于传感器系列,并具有指向成员的指针: / p>

You can make the field dependent on the sensor family with a pointer to member:

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;
}

你也可以放入一个 typedef 传感器的数据类型:

You can also put in, say, a typedef for the sensor's data type:

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;
}

您可能需要 const static

这篇关于使用模板而不是开关的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆