我正在创建一个 DNS 名称解析器。在解析返回的数据包时,我读取了 RR 类型,然后将其通过 switch 以初始化类 Record 的派生类型。记录类型是一个大型枚举类型。我使用模板专业化将枚举映射到结构。
template < QueryType n >
struct Struct;
template <> struct Struct< DNS_Q_A > { typedef A Type; };
template <> struct Struct< DNS_Q_CNAME > { typedef CNAME Type; };
template < QueryType n > struct Struct { typedef UNKNOWN Type; };
目前我有 4 个 switch 语句,它们都做非常相似的事情。即调用 operator new,placement new,用于复制和移动 c'tors。这是需要维护的大量代码。我希望只有 1 个 switch 语句,我可以在其中传递某种类型的对象,其中包含要执行的函数、返回类型和 n 个参数。
switch 语句如下所示:
switch ( nType )
{
case DNS_Q_A:
pInstance = new ( &Container ) Struct< DNS_Q_A >::Type( dynamic_cast< const Struct< DNS_Q_A >::Type& >( Other ) );
break;
case DNS_Q_CNAME:
pInstance = new ( &Container ) Struct< DNS_Q_CNAME >::Type( dynamic_cast< const Struct< DNS_Q_CNAME >::Type& >( Other ) );
break;
}
如您所见,除了对结构类型的依赖之外,每种情况都是相同的。这对我来说是“模板”,但我不知道如何传入一个对象。
我仅限于编码 4 个开关还是有办法?请不要引用“Boost”,此代码必须独立于任何其他库。
解决方案:(感谢 Jan Hudec)
template< template < class > class Action >
typename Action< Struct< DNS_Q_A >::Type >::result_type
CreateRecord (
unsigned n,
typename Action< Struct< DNS_Q_A >::Type >::first_argument_type arg1,
typename Action< Struct< DNS_Q_A >::Type >::second_argument_type arg2 )
{
typedef typename typename Action< Struct< DNS_Q_A >::Type >::result_type ReturnType;
switch ( n )
{
case DNS_Q_A: return static_cast< ReturnType >( Action< Struct< DNS_Q_A >::Type >()( arg1, arg2 ) );
case DNS_Q_NS: return static_cast< ReturnType >( Action< Struct< DNS_Q_NS >::Type >()( arg1, arg2 ) );
/*...*/
}
}
Action 结构定义为:
template < typename T >
struct Copy : std::binary_function< storage_type&, const Record&, Record* >
{
Record* operator() ( storage_type& Storage, const Record& Obj )
{
return new ( &Storage ) T( dynamic_cast< const T& >( Obj ) );
}
};
template < typename T >
struct Move : std::binary_function< storage_type&, Record&&, Record* >
{
Record* operator() ( storage_type& Storage, const Record& Obj )
{
return new ( &Storage ) T( dynamic_cast< const T& >( std::move( Obj ) ) );
}
};
并将 Switch 语句替换为:
pInstance = CreateRecord< Copy >( nType, Container, Other );