2011-02-12 44 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."); 
    } 
} 

不是特别大,但是这是好得不能再好,我猜。 ..