DNS名前リゾルバーを作成しています。返されたパケットを解析している間、RRタイプを読み取り、それをスイッチに渡して、派生タイプのクラス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ステートメントを持っていますが、これらはすべて非常によく似た処理を行います。つまり、コピーと移動の両方の演算子について、演算子new、配置newを呼び出します。これは維持する必要のある多くのコードです。実行する関数を含むある種のオブジェクトを渡して、型とn個のパラメーターを返すことができるswitchステートメントを1つだけ作成したいと思います。
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」を引用しないでください。このコードは他のライブラリから独立している必要があります。
解決策:(JanHudecに感謝します)
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 ) );
/*...*/
}
}
アクション構造体は次のように定義されています。
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 );