[英]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_if
與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>
{
...
};
您可以使用std::is_floating_point
來匹配浮點類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.