6

我有一些模板代码适用于 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,双倍的, ...)。

4

1 回答 1

3

我很确定Visual Studio-2010 支持<type_traits>. 您可以std::enable_ifstd::is_enum.

template <typename ValueType, typename Enable = void>
class Extractor {
 public:
  ValueType extract(API_Secret value);
};

template <typename ValueType>
class Extractor<ValueType, typename std::enable_if<std::is_enum<ValueType>::value>::type>
{
 ...
};


您可以使用相同的方法来匹配浮点类型std::is_floating_point

于 2013-02-11T22:19:04.653 回答