2011-02-12 42 views
11

我正在尋找一個哈克一種解決以下問題: GCC 4.4或以上版本接受以下的C++ 0x代碼:「枚舉類」仿真或固體替代的MSVC 10.0

enum class my_enum 
{ 
    value1, 
    value2 
}; 

哪允許使用像這樣:

my_enum e = my_enum::value1; 

帶來所有的花裏胡哨帶來。我想使此代碼與MSVC 2010兼容,以便使用語法不會更改。我已經在here之前對此進行了思考,並且接受的答案有效,但是對於enum和enum值的兩個不同名稱的需求正在破壞這兩種方法的兼容性。這使得替換C++ 0x代碼當然是不可用的。我想知道是否有一些#undef#define詭計可以解決這個問題,讓我使用enum class類似的語法(也許沒有嚴格的類型安全等),但至少是相同的語法。謝謝!

回答

20

我剛剛發現了一個問題,詹姆斯的不錯的黑客(這是我迄今爲止一直在使用),並解決了這個問題。當我嘗試爲my_enum定義一個流運算符時,我發現了這個問題。

#include <iostream> 

struct my_enum { 
    enum type { 
     value1, 
     value2 
    }; 

    my_enum(type v) : value_(v) { } 

    operator type() const { return value_; } 

private: 

    type value_; 
}; 

std::ostream& 
operator<<(std::ostream& os, my_enum v) 
{ 
    return os << "streaming my_enum"; 
} 

int main() 
{ 
    std::cout << my_enum::value1 << '\n'; 
} 

的輸出是:

0 

問題是my_enum::value1具有不同的類型my_enum。這是詹姆斯的黑客攻擊,我想出了。

struct my_enum 
{ 
    static const my_enum value1; 
    static const my_enum value2; 

    explicit my_enum(int v) : value_(v) { } 

    // explicit // if you have it! 
     operator int() const { return value_; } 

private: 

    int value_; 
}; 

my_enum const my_enum::value1(0); 
my_enum const my_enum::value2(1); 

注:

  1. 除非由枚舉基另外指明,否則下面的類型範圍化枚舉的是int
  2. 允許向和從基礎整型的顯式轉換。但隱式轉換不是。盡你所能。
  3. 由於需要枚舉值兩次,所以這種黑客比詹姆斯更像皮塔。我希望沒有範圍枚舉支持的編譯器迅速滅絕!
5

請勿使用此解決方案。查看霍華德接受的更好解決方案的答案。我在這裏留下這個帖子是因爲霍華德的回答指的是它。

如果您需要能夠使用尚未支持新的,尚未標準或尚未廣泛實現的語言功能的編譯器編譯代碼,最好避免在代碼中使用該語言功能。

這就是說,作爲一個黑客的解決方法,你可以用一個structenum並且使用了雙隱式轉換:

struct my_enum { 
    enum type { 
     value1, 
     value2 
    }; 

    my_enum(type v) : value_(v) { } 

    operator type() const { return value_; } 

private: 

    type value_; 
}; 
+0

這是一種模式?你爲什麼認爲這是一個黑客?它很整潔。 – Inverse 2011-02-12 21:09:23

+1

@反:如果你反覆使用它會成爲一種模式:-)。在結構體或命名空間中枚舉枚舉以防止名稱空間污染是一種常用技術,我一直使用(主要是)。使用隱式轉換來允許使用封裝結構,就好像它是枚舉一樣,這不是一種常見模式,至少在我沒有閱讀過的任何代碼中都是如此。由於隱含轉換,我對此保持警惕:我不斷髮現隱式轉換允許您編寫細微代碼的不同方式...... – 2011-02-13 15:14:50

0

我一直在爭取一整天,找到一個真正的最佳解決方案,但似乎並沒有一個。我需要我的枚舉是

  1. 不隱式轉換爲整型
  2. 可用在switch聲明
  3. 可用作非類型模板參數

在紛紛拿出以下碼,在霍華德Hinnant(欣南特)的解決方案內置:

struct DataType 
{ 
    struct integral { 
     enum type { None, Single, Double, Int }; 
    }; 

    typedef typename integral::type integral_type; 

    explicit DataType(integral_type v) : val(v) {} 
    integral_type integral_value() const { return val; } 

    bool operator==(const DataType& s) const { return val == s.val; } 
    bool operator!=(const DataType& s) const { return val != s.val; } 

    static const DataType None; 
    static const DataType Single; 
    static const DataType Double; 
    static const DataType Int; 

private: 
    integral_type val; 
}; 

.cpp文件:

const DataType DataType::None (DataType::integral::None); 
const DataType DataType::Single (DataType::integral::Single); 
const DataType DataType::Double (DataType::integral::Double); 
const DataType DataType::Int (DataType::integral::Int); 

作爲非類型模板參數:

template <DataType::integral_type> 
struct DataTypeTraits; 

template <> 
struct DataTypeTraits<DataType::integral::Single> 
{ 
    enum { size = 4 }; 
}; 

在開關:

size_t get_size(DataType type) 
{ 
    switch (type.integral_value()) { 
     case DataType::integral::Single: return DataTypeTraits<DataType::integral::Single>::size; 
     case DataType::integral::Double: return DataTypeTraits<DataType::integral::Double>::size; 
     case DataType::integral::Int:  return DataTypeTraits<DataType::integral::Int>::size; 
     default:       throw std::logic_error("Unknown data type."); 
    } 
} 

不是特別大,但是這是好得不能再好,我猜。 ..