簡體   English   中英

C ++將浮點值轉換為枚舉 - 但不是VS 2010

[英]C++ casting a floating point value to an enum - but not with VS 2010

我有一些適用於Xcode 4.5和LLVM 3.0的模板代碼,但是使用VS 2010 Express C ++工具鏈(v 10.0.30319.1)失敗了。

我正在使用我無法控制的第三方API。 它為我的代碼提供的值為黑盒'blob',只能由API函數解釋:

// 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);

即類模板使用static_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> ),我可以使用Extractor<int> ,然后將其分配給目標MyEnum變量。 但是,此模板實際上用作調用包裝函數的較大系統的一部分,在這種情況下,包裝函數采用MyEnum值。 這可以防止模板正確匹配,因為ValueType參數實際上是從包裝函數的簽名中自動獲取的。

或者,是否可以編寫僅與enum類型匹配的Extractor模板特化? 然后我可以先演成一個整體類型。 或者也許基本模板總是可以首先轉換為int,然后我可以編寫一個不執行此操作的浮點專門化 - 但我不確定如何編寫捕獲所有浮點類型的模板(float,加倍,...)。

我很確定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來匹配浮點類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM