3

我正在实现一个协议,其中一台主机可以接收单字节命令。

虽然一个字节有 256 个可能的值,但其中只有少数是有效的。

当然我可以写这样的东西:

bool is_valid(uint8_t command)
{
  switch (command)
  {
    case 0x00:
    case 0x01:
    case 0xa0:
    case 0xa1:
      return true;
  }

  return false;
}

在运行时检查接收到的命令的有效性。

不幸的是,我还必须为这些命令中的每一个维护一个名称列表,这将迫使我编写另一个非常接近is_valid()但会返回命令名称的函数。这样做会使我复制有效命令的列表,我不喜欢这样。

我想知道是否有一种方法可以使用元编程来仅声明一次有效命令。

就像是:

template <uint8_t Value>
struct valid_value_type;

struct valid_value_type<0x00> { static const std::string name = "Stop command"; };
struct valid_value_type<0x01> { static const std::string name = "Start command"; };

但是,我无法达到任何令人满意的结果(理解“编译和工作”),而且我不知道如何生成一个自适应is_valid()函数来自动考虑这些模板声明的存在。

这甚至可能吗?如果是这样,你会怎么做?

注意:遗憾的是 C++11 不是一个选项,但出于好奇,我也对该解决方案感兴趣。

4

2 回答 2

2

除非您在嵌入式环境中,否则 a 只有 256 个可能的值uint8_t,因此用它编写查找表并不可怕......

char const * cmds[256] = {};
void cmds_init(char const * (&cmds)[256]) {
   cmds[0x00] = "Stop command";
// ...
}

然后对有效命令的测试只是在查找表中找到名称:

bool is_valid(uint8_t cmd) {
   return cmds[cmd] != 0;
}

如果有效命令的数量远小于 256,您可以实现一个函数,该函数使用开关返回名称,如果命令未知,则返回 null,并使用相同的方法。

于 2013-03-04T20:33:01.553 回答
1

下面的事情会做吗?

template <uint8_t Value>
struct valid_value_type
{
  static char const *const name = 0;
};

template<>
struct valid_value_type<0x00>
{
  static char const *const name = "Stop command";
};

template<>
struct valid_value_type<0x01>
{
  static char const *const name = "Start command";
};

template <uint8_t N>
bool is_valid_value_type_helper(uint8_t value, valid_value_type<N>)
{
  return((value == N) ? valid_value_type<N>::name != 0 : check_valid_value_type_helper(value, valid_value_type<N-1>()));
}

bool is_valid_value_type_helper(uint8_t value, valid_value_type<0>)
{
  return(value == 0 && valid_value_type<0>name != 0);
}

bool is_is_valid_value_type(uint8_t value)
{
  return(is_valid_value_type_helper(value, valid_value_type<0xff>());
}

大概可以简化一点...

于 2013-03-04T22:03:14.197 回答