C ++将浮点值转换为枚举 - 但不与VS 2010 [英] C++ casting a floating point value to an enum - but not with VS 2010

查看:1196
本文介绍了C ++将浮点值转换为枚举 - 但不与VS 2010的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些模板代码与Xcode 4.5和LLVM 3.0工作正常,但失败与VS 2010 Express C ++工具链(v 10.0.30319.1)。

I have some template code that works fine with Xcode 4.5 and LLVM 3.0, but fails with the VS 2010 Express C++ toolchain (v 10.0.30319.1).

I使用我无法控制的第三方API。它为我的代码提供的值为黑盒blob,只能由API函数解释:

I'm using a third-party API that I have no control over. It provides values to my code as black-box 'blobs' that can only be interpreted by API functions:

// 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.之间的区别。 LLVM,以下将编译(作为完整程序的一部分):

Now for the difference between Xcode, LLVM and VS 2010. In Xcode & LLVM, the following will compile (as part of the full program):

enum MyEnum {
  Enum0,
  Enum1,
};
Extractor<MyEnum> ee;
MyEnum ve = ee.extract(secret0);

类模板使用 static_cast 从浮点数转换为枚举。这似乎工作正常,此网页的说明部分表明这是有效的:

I.e. the class template uses a static_cast to convert from a floating point number to an enum. This seems to work fine, and the explanation section of this page suggests this is valid:


8)整数,浮点型或枚举类型可以转换为任何枚举类型如果转换为枚举的底层类型的表达式的值不是目标枚举值之一,则未指定结果)

8) Integer, floating-point, or enumeration type can be converted to any enumeration type (the result is unspecified if the value of expression, converted to the enumeration's underlying type, is not one of the target enumeration values)

VS2010,遇到以下编译器错误:

However with VS2010, the following compiler error is encountered:


错误C2440:'static_cast':无法从'double'转换为'MyEnum' p>

error C2440: 'static_cast' : cannot convert from 'double' to 'MyEnum'

     Conversions between enumeration and floating point values are no longer allowed


而此 MSDN文章似乎通过不提及浮点类型并明确说明整数值来确认这一点:

And this MSDN article seems to confirm this by not mentioning floating-point types and explicitly stating 'integral' value:


static_cast操作符可以将整数值显式转换为枚举类型。如果整数类型的值不在枚举值范围内,则生成的枚举值未定义。

The static_cast operator can explicitly convert an integral value to an enumeration type. If the value of the integral type does not fall within the range of enumeration values, the resulting enumeration value is undefined.

在VS 2010和其他编译器之间有一个显着的差异。我想知道这是否是可以在VS 2010中绕过的东西?它是VS 2010简单不支持的语言的较新特性吗?

So it appears that there is a significant difference here between VS 2010 and the other compilers. I am wondering whether this is something that can be bypassed in VS 2010? Is it a newer feature of the language that VS 2010 simply doesn't support? However I query this as the error message says "no longer allowed", implying it's explicitly disallowed.

我知道一个解决方法 - 而不是转换到一个枚举(与 Extractor< MyEnum> ),我可以使用 Extractor< int> ,然后简单地将它分配给目标MyEnum变量。但是,此模板实际上用作调用包装函数的较大系统的一部分,在这种情况下,包装函数接受一个MyEnum值。这会阻止模板正确匹配,因为ValueType参数实际上是从包装函数的签名中自动选取的。

I know of a workaround - instead of casting to an enum (with Extractor<MyEnum>), I can use an Extractor<int> instead, and then simply assign this to the target MyEnum variable. However this template is actually used as part of a larger system that calls wrapped functions, and in this case the wrapped function takes a MyEnum value. This prevents the template from matching properly as the ValueType parameter is actually picked up automatically from the signature of the wrapped function.

或者,可以写一个模板专用化仅匹配枚举类型的提取器?然后我可以铸成一个完整的类型。或者也许基本模板总是可以转换为int首先,然后我可以写一个浮点特殊化,不这样做 - 但我不知道如何写一个模板捕获所有的浮点类型(浮点, double,...)。

Alternatively, is it possible to write a template specialization of Extractor that matches enum types only? Then I can cast to an integral type first. Or maybe the base template could always cast to an int first, then I could write a floating-point specialization that doesn't do this - but I'm not sure how to write a template that catches all floating-point types (float, double, ...).

推荐答案

我确定< type_traits> .com / en-us / library / vstudio / bb982077%28v = vs.100%29.aspxrel =nofollow 。您可以使用 std :: enable_if 以及 std :: is_enum

I'm pretty sure Visual Studio-2010 supports <type_traits>. You can use std::enable_if along with std::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>
{
 ...
};



您也可以使用<$ c来匹配浮点类型$ c> std :: is_floating_point 。

这篇关于C ++将浮点值转换为枚举 - 但不与VS 2010的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆