サードパーティのSDKは、いくつかのtypedefを定義しています。
typedef unsigned char SDK_BYTE
typedef double SDK_DOUBLE
typedef unsigned char SDK_BOOLEAN
また、バリアント型SdkVariantを定義します。
class SdkVariant
{
public:
enum SdkType { SdkByte, SdkDouble, SdkBoolean };
bool toByte(SDK_BYTE&);
bool toDouble(SDK_DOUBLE&);
bool toBool(SDK_BOOLEAN&);
SdkType type();
};
このようなバリアントから値を取得することは、次のようになります(含まれている値のタイプがわかっていると仮定します)。
SdkVariant variant(foobar());
double value;
bool res = variant.toDouble(value);
if (!res)
diePainfully();
else
doSomethingWith(value);
これは非常に冗長であるため、値の取得とエラー処理を実行できるvariant_cast-function-classを提供したいと思います。
// general interface:
template<class T>
class variant_cast
{
public:
T operator()(const SdkVariant& variant);
};
// template specializations:
template<>
SDK_DOUBLE variant_cast<SDK_DOUBLE>::operator()(const SdkVariant& variant)
{
SDK_DOUBLE value;
bool res = variant.toDouble(value);
if (!res)
diePainfully();
return value;
}
template<>
SDK_BYTE variant_cast<SDK_BYTE>::operator()(const SdkVariant& variant)
{
SDK_BYTE value;
bool res = variant.toByte(value);
if (!res)
diePainfully();
return value;
}
template<>
SDK_BOOLEAN variant_cast<SDK_BOOLEAN>::operator()(const SdkVariant& variant)
{
SDK_BOOLEAN value;
bool res = variant.toByte(value);
if (!res)
diePainfully();
return value;
}
SDK_BYTEとSDK_BOOLEANは同じタイプ(unsigned char)であるため、これはコンパイルされません(C2995:関数テンプレートは既に定義されています)。私の考えは、プリプロセッサにSDK_BYTEとSDK_BOOLEANが同じであることを確認させ、同じである場合は、両方に単一のテンプレート特殊化を定義することです。それらが異なる場合は、上記の2つの別個の専門分野を使用する必要があります。このような:
#if SDK_BYTE == SDK_BOOLEAN
template<>
SDK_BYTE variant_cast<SDK_BYTE>::operator()(const SdkVariant& variant)
{
SDK_BYTE value;
bool res;
if (variant.type() == SdkByte)
res = variant.toByte(value);
else
res = variant.toBool(value);
if (!res)
diePainfully();
return value;
}
#else
// code from above
#endif
上記のコードの問題は、プリプロセッサが2つのtypedefを解決できないように見えることです。前処理中に2つのtypedefを(正しく)比較する方法はありますか?そうでない場合、コンパイラがtypedefを解決するのを妨げて、SDK_BYTEとSDK_BOOLEANの2つの異なるテンプレート特殊化を受け入れる方法はありますか?そうでない場合でも、単一のテンプレートの特殊化を提供し、BOOST_STATIC_ASSERTを使用して、SDK_BYTEとSDK_BOOLEANが等しくない場合にコンパイラーを失敗させることができますが、問題を解決するためのより良い方法はありますか?