我正在实现一个协议,其中一个主机可以接收一个字节的命令。
虽然一个字节有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()
函数,该函数会自动考虑这些模板声明的存在。 / p>
这甚至可能吗?如果是这样,你会怎么做?
注意:遗憾的是C ++ 11不是一个选项,但出于好奇,我对解决方案感兴趣。
答案 0 :(得分:2)
除非您处于嵌入式环境中,否则uint8_t
只有256个可能的值,因此使用该值编写查找表并不可怕......
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,并使用相同的方法。
答案 1 :(得分: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>());
}
它可能会简化一点......