如何使用超过max int的值创建枚举?

vgo*_*anz 10 c++ variables enums

我正在使用c ++创建枚举,以使用二进制标志创建有限状态机.看起来像:

enum VStates
{
    NEUTRAL         =   0x00000000,     // 000000
    //  Physical Status
    DRY             =   0x00000001,     // 000001
    WET             =   0x00000002,     // 000010
    HOT             =   0x00000004,     // 000100
    COLD            =   0x00000008,     // 001000
    BURNED          =   0x00000016,     // etc..
    FROZEN          =   0x00000032,
    EROS            =   0x00000064,     // 
    THANATOS        =   0x00000128,     // 
    SLEEP           =   0x00000256,
    STUNNED         =   0x00000512,
    PARALYZED       =   0x00001024,
    POISONED        =   0x00002048,     //
    BLIND           =   0x00004096,
    SOFT            =   0x00008192,     // Flexible
    TOUGH           =   0x00016384,     // Resistent
    MAGNETIZED      =   0x00032768,
    POSSEDERUNT     =   0x00131072,     //
    // Mental Status
    ANGRY           =   0x00262144,
    DRUGGED         =   0x00524288, // Drugs Meaning
    HORNY           =   0x01048576, // Sexual Meaning
    // Material Status
    METAL           =   0x02097152,
    WOOD            =   0x04194304,
    GLASS           =   0x08388608,
    AIR             =   0x16777216,
    EARTH           =   0x33554432,
    DUST            =   0x67108864,
    LIGHT           =   0x134217728,
    SHADOW          =   0x268435456,
    WATER           =   0x536870912,
    // Total Status
    PROTECTED       =   0x1073741824,
    INVULNERABLE    =   0x2147483648

};
Run Code Online (Sandbox Code Playgroud)

某些状态是不兼容的,因此我使用Bitwise运算符来管理它们.现在,我的编译器说:

warning: integer constant is too large for 'long' type
Run Code Online (Sandbox Code Playgroud)

这是声明此枚举的正确方法吗?我喜欢避免警告,我该如何解决这个问题?

Dav*_*one 13

在C++ 11中,您可以指定枚举的基础类型.

#include <cstdint>

enum VStates : uint64_t {
    // Values
}
Run Code Online (Sandbox Code Playgroud)

另外,我建议不要计算所有这两种权力.您在计算中通过写入十六进制常量但在给出基数为10的数字的数字时出错.但是,我不建议重新计算所有这些,而是​​建议:

#include <cstdint>

enum VStates : uint64_t {
    NEUTRAL = 0ULL,
    DRY = 1ULL << 0,
    WET = 1ULL << 1,
    HOT = 1ULL << 2,
    COLD = 1ULL << 3,
    // etc.
}
Run Code Online (Sandbox Code Playgroud)

那你肯定不会犯错.所述ULL后缀确保文字被接受为至少64位宽的整数.


Hos*_*ork 11

(注意:为了使我的答案完整,我将添加一些我没有花时间注意的东西,但其他人已经指出:你正在使用0x前缀,这意味着你的数字将被解释为十六进制.他们实际上并不是是2的幂,你的位标测试不会有效!)

如果您的枚举失控,请不要使用枚举类型.使用类似的东西std::bitset.然后你的枚举可以只是一个简单的编号列表,用于集合中位的位置......并且你不会以指数方式耗尽枚举空间!

例如:

enum VState {
    NEUTRAL,
    DRY,
    WET,
    COLD,
    BURNED,
    FROZEN,
    /* ... */
    VState_Max
};

bitset<VState_Max> state;

state[COLD] = true;
if (state[COLD]) {
    cout << "I am cold\n";
}
Run Code Online (Sandbox Code Playgroud)

现在你的枚举只是小的,可维护的数字,你不必担心在64位平台上或其他什么.

我注意到您在原始示例中为NEUTRAL赋予了值"0".如果您的意图是可以将其与其他东西结合使用......例如能够进行state = NEUTRAL | INVULNERABLE | SHADOW单独测试NEUTRAL,那么之前就无法使用.它现在......你只是将它保存在枚举中以索引bitset.

如果它打算作为"无设置"的名称,那么你将从枚举中删除它,而不是测试没有设置的位:

if (state.none()) {
    // we are in the "NEUTRAL" state of nothing set...
}
Run Code Online (Sandbox Code Playgroud)

...如果你想把所有的比特都设置为假,那你就去:

state.reset();
Run Code Online (Sandbox Code Playgroud)

  • 这是一个比我更好的答案,因为你纠正了真正的根本问题.对标志集合使用`std :: bitset`,而不是枚举.甚至比使用枚举索引更好的方法是将它包装在一个具有`std :: bitset`作为具有命名成员访问函数的私有成员的类中.`class VStates {public:bool is_dry()const {return bits [1]; } ...};` (4认同)