我有一些模板代码适用于 Xcode 4.5 和 LLVM 3.0,但在 VS 2010 Express C++ 工具链(v 10.0.30319.1)中失败。
我正在使用我无法控制的第三方 API。它为我的代码提供值作为只能由 API 函数解释的黑盒“blob”:
// API_Secret is a black-box encapsulation of a floating-point number or a boolean value.
// It is provided by a third-party API, with associated access functions.
// For all intents and purposes, it's a complete black box.
// This enum represents the internal 'type' of a secret value.
enum API_SecretTypeEnum {
API_Number,
API_Boolean,
};
// Other API declarations:
API_SecretTypeEnum API_GetType(const API_Secret &value);
double API_AsNumber(const API_Secret &value);
bool API_AsBoolean(const API_Secret &value);
// my code:
template <typename ValueType>
class Extractor {
public:
ValueType extract(API_Secret value) {
if (API_GetType(value) == API_Number) {
return static_cast<ValueType>(API_AsNumber(value));
} else if (API_GetType(value) == API_Boolean) {
return API_AsBoolean(value) ? ValueType(1) : ValueType(0);
}
return ValueType();
}
};
// boolean specialization - not 100% sure it's needed though
template<>
class Extractor <bool> {
public:
bool extract(API_Secret value) {
return API_AsBoolean(value);
}
};
然后,稍后:
API_Secret API_GetSomeValue(int some_sort_of_handle);
// get some black-box values from the API
API_Secret secret0 = API_GetSomeValue(0);
API_Secret secret1 = API_GetSomeValue(1);
API_Secret secret2 = API_GetSomeValue(2);
// for certain external reasons we expect this to be an integer representation:
Extractor<int> e0;
int v0 = e0.extract(secret0);
// for certain external reasons we expect this to be a double representation:
Extractor<double> e1;
double v1 = e1.extract(secret1);
// for certain external reasons we expect this to be a boolean representation:
Extractor<bool> e2;
bool v2 = e2.extract(secret2);
现在来了解 Xcode、LLVM 和 VS 2010 之间的区别。在 Xcode 和 LLVM 中,将编译以下内容(作为完整程序的一部分):
enum MyEnum {
Enum0,
Enum1,
};
Extractor<MyEnum> ee;
MyEnum ve = ee.extract(secret0);
即类模板使用 astatic_cast
从浮点数转换为枚举。这似乎工作正常,本页的解释部分表明这是有效的:
8) 整数、浮点数或枚举类型可以转换为任何枚举类型(如果转换为枚举的基础类型的表达式的值不是目标枚举值之一,则结果未指定)
但是使用 VS2010,会遇到以下编译器错误:
错误 C2440:“static_cast”:无法从“double”转换为“MyEnum”
Conversions between enumeration and floating point values are no longer allowed
这篇MSDN 文章似乎通过不提及浮点类型并明确说明“整数”值来证实这一点:
static_cast 运算符可以将整数值显式转换为枚举类型。如果整数类型的值不在枚举值范围内,则生成的枚举值是未定义的。
因此,VS 2010 和其他编译器之间似乎存在显着差异。我想知道这是否可以在 VS 2010 中绕过?它是 VS 2010 根本不支持的语言的新功能吗?但是,我对此进行了查询,因为错误消息显示“不再允许”,这意味着它被明确禁止。
我知道一种解决方法 -Extractor<MyEnum>
我可以使用 anExtractor<int>
而不是强制转换为枚举(使用 ),然后只需将其分配给目标 MyEnum 变量。然而,这个模板实际上用作调用包装函数的更大系统的一部分,在这种情况下,包装函数采用 MyEnum 值。这会阻止模板正确匹配,因为 ValueType 参数实际上是从包装函数的签名中自动提取的。
或者,是否可以编写enum
仅匹配类型的 Extractor 模板特化?然后我可以先转换为整数类型。或者,也许基本模板总是可以先转换为 int,然后我可以编写一个不这样做的浮点特化 - 但我不确定如何编写一个捕获所有浮点类型的模板(float,双倍的, ...)。