“枚举类”仿真或MSVC 10.0的固体替代品

时间:2011-02-12 19:58:38

标签: c++ class visual-c++ enums c++11

我正在寻找一种针对以下问题的hacky解决方案: GCC 4.4+接受以下c ++ 0x代码:

enum class my_enum
{
    value1,
    value2
};

允许这样使用:

my_enum e = my_enum::value1;
这带来了所有的钟声和口哨声。我想使这段代码与MSVC 2010兼容,使用语法不会改变。我已经在here之前对此进行了思考,并且接受的答案有效,但是枚举和枚举值的两个不同名称的需要正在破坏这两种方法的兼容性。这使得它当然无法替换C ++ 0x代码。我想知道是否有一些#undef#define技巧可以解决这个问题,允许我使用 enum class - 就像语法一样(可能没有严格的类型安全等) ,但至少相同的语法。谢谢!

3 个答案:

答案 0 :(得分:21)

我刚刚发现詹姆斯的好黑客(我以前一直在使用)的问题,并解决了这个问题。当我尝试为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. 除非 enum-base 另有指定,否则作用域枚举的基础类型为int
  2. 允许与底层整数类型进行显式转换。但隐性转换不是。尽你所能。
  3. 这个黑客比詹姆斯更像是一个皮塔饼,因为需要两次枚举这些值。我希望没有范围枚举支持的编译器迅速灭绝!

答案 1 :(得分:5)

请勿使用此解决方案。请参阅霍华德接受的答案以获得更好的解决方案。我要离开这篇文章,因为霍华德的回答是指它。

如果您需要能够使用尚不支持新的,尚未标准或尚未广泛实现的语言功能的编译器来编译代码,则最好避免在代码中使用该语言功能。

也就是说,作为黑客解决方法,您可以将enum打包在struct中并使用一对隐式转换:

struct my_enum {
    enum type { 
        value1, 
        value2 
    };

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

    operator type() const { return value_; }

private:

    type value_;
};

答案 2 :(得分:0)

我一直在争取一整天找到一个真正的最佳解决方案,但似乎没有一个。我需要我的枚举

  1. 不可隐式转换为整数类型
  2. 适用于switch声明
  3. 可用作非类型模板参数
  4. 提出以下代码,建立在Howard 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.");
        }
    }
    

    不是特别好,但是它确实如此好,我猜......