我想将ICMP header定义为广告连播类型:
struct ICMPHeader
{
uint8_t Type; // ICMP type
uint8_t Code; // Subtype, value is dependent on ICMP type.
uint16_t Checksum; // Error checking data. See RFC 1071
uint32_t RestOfHeader; // Varies based on ICMP type and code.
};
对于ICMPType
字段,我可以使用强类型枚举来使其更好一些:
enum class ICMPType : uint8_t
{
EchoReply = 0,
Reserved1 = 1,
Reserved2 = 2,
DestinationUnreachable = 3,
SourceQuench = 4
// etc...
};
struct ICMPHeader
{
ICMPType Type; // ICMP type
uint8_t Code; // Subtype, value is dependent on ICMP type.
uint16_t Checksum; // Error checking data. See RFC 1071
uint32_t RestOfHeader; // Varies based on ICMP type and code.
};
现在,我自然也希望将Code
字段指定为枚举。如果我可以使用模板特化语法会很好,但快速测试表明它不起作用:
// Compiler error
template<ICMPType>
enum class ICMPCode;
template<>
enum class ICMPCode<ICMPType::DestinationUnreachable>
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
};
一种选择是将它们包装在结构中:
// Meaning of ICMP code is dependent on ICMP type.
template<ICMPType>
struct ICMPCode;
// Subcodes for DestinationUnreachable
template<> struct ICMPCode<ICMPType::DestinationUnreachable>
{
enum class Code : uint8_t
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
// etc...
};
};
// Access: ICMPCode<ICMPType::DestinationUnreachable>::Code::DestinationHostUnreachable
但是这样做会让我觉得我只是乱搞并使事情过于复杂。
我想这是一个更一般的问题的具体例子:如何设置类型和子类型的系统?有什么建议吗?
PS:
示例代码:
#include <iostream>
// Trying to model ICMP types and codes with strongly typed enums
// See also http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Header
enum class ICMPType : uint8_t
{
EchoReply = 0,
Reserved1 = 1,
Reserved2 = 2,
DestinationUnreachable = 3,
SourceQuench = 4
// etc...
};
// Meaning of ICMP code is dependent on ICMP type.
template<ICMPType>
struct ICMPCode;
// Subcodes for DestinationUnreachable
template<> struct ICMPCode<ICMPType::DestinationUnreachable>
{
enum class Code : uint8_t
{
DestinationNetworkUnreachable = 0,
DestinationHostUnreachable = 1,
DestinationProtocolUnreachable = 2
// etc...
};
};
ICMPCode<ICMPType::DestinationUnreachable>::Code GetReasonWhyDestinationIsUnreachable()
{
return ICMPCode<ICMPType::DestinationUnreachable>::Code::DestinationHostUnreachable;
}
int main()
{
std::cout << static_cast<int>(GetReasonWhyDestinationIsUnreachable()) << std::endl;
}
答案 0 :(得分:1)
我不认为您可以在编译时静态地执行此操作,因为您在运行时更改了ICMPType
。
我建议:
code
范围创建一个枚举。ICMPHeader
类型,并在那里丢失类型变量。)ICMPType
枚举的专用类型。这应该是一种非常灵活的方法,但根据类型简单地转换代码的值可能足够且更容易处理。
在你的例子中,你只是回到一个int,虽然它剥离了你刚刚设定的所有东西......?
编辑 - 如果所有容器都从公共基类继承,那么您可以提供一个通用的GetDescription()方法,孩子们可以填充这些方法。像这样抽象细节使得设计很干净......