第 3 方 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;
}
这不会编译(C2995:已定义函数模板),因为 SDK_BYTE 和 SDK_BOOLEAN 是相同的类型(无符号字符)。我现在的想法是让预处理器检查 SDK_BYTE 和 SDK_BOOLEAN 是否相同,如果是,则为两者定义一个模板特化。如果它们不同,它应该使用上面的两个单独的专业化。像这样:
#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
上面代码的问题是,预处理器似乎不可能解析这两个 typedef。有没有办法在预处理期间(正确地)比较两个 typedef?如果没有,有没有办法阻止编译器解析 typedef,以便它接受 SDK_BYTE 和 SDK_BOOLEAN 的两种不同的模板特化?如果没有,如果 SDK_BYTE 和 SDK_BOOLEAN 不相等,我仍然可以提供单一模板专业化并使用 BOOST_STATIC_ASSERT 使编译器失败,但是有没有更好的方法来解决我的问题?