I'm making a enum in c++ to make a finite state machine using binary flags. It looks like:
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
};
Some status are incompatibles, so I use Bitwise operators to manage them. Now, my compiler say:
warning: integer constant is too large for 'long' type
Is this the correct way to declare this enum? I like avoid warning so, How can I resolve this problem?
In C++11, you can specify the underlying type of the enum.
#include <cstdint>
enum VStates : uint64_t {
// Values
}
On a side note, I recommend against calculating out all of those powers of two. You made an error in your calculations by writing a hex constant but giving it the digits of a base-10 numeral. However, rather than recalculating all of those, I recommend something like:
#include <cstdint>
enum VStates : uint64_t {
NEUTRAL = 0ULL,
DRY = 1ULL << 0,
WET = 1ULL << 1,
HOT = 1ULL << 2,
COLD = 1ULL << 3,
// etc.
}
Then you are sure not to make a mistake. The ULL
suffix ensures that the literal is accepted as at least a 64-bit wide integer.
(Note: to make my answer complete I'll add in something I didn't take time to notice but others have pointed out: you're using the 0x
prefix, which means your numbers would be interpreted as hexadecimal. They'd not actually be powers of two, and your bitflag tests would not have worked!)
If your enumerations are running out of control like this, don't use an enumerated type. Use something like a std::bitset
. Then your enum can just be a simple numbered list of names for the positions of the bits in the set...and you won't be exhausting your enumeration space exponentially!
For example:
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";
}
Now your enum is just small, maintainable numbers and you don't have to worry about being on a 64-bit platform or whatnot.
I note that you gave a value of "0" for NEUTRAL in your original example. If your intent was to have it be possible to use this in combination with other things...such as being able to be state = NEUTRAL | INVULNERABLE | SHADOW
and individually test for NEUTRAL
, that wouldn't have worked before. It will now...you'd just keep it in the enumeration for indexing the bitset.
But if it intended as a name for "nothing set", then you would remove it from the enum and instead test for no bits set with:
if (state.none()) {
// we are in the "NEUTRAL" state of nothing set...
}
...and if you wanted to set all the bits to false, you'd go with:
state.reset();
The enumeration has 31 non-zero values, so they can all fit in a 32-bit unsigned value. The problem is that the values here aren't bit-values. Either write them as decimal values (remove the 0x
from the front) or write them as hexadecimal values (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, etc.) I personally don't like it, but some people write this kind of constant with shifts: 1<<0, 1<<1, 1<<2, 1<<3, etc.
If you are using C++11, you can declare a strongly-typed enum with a defined type as unsigned long long
(_int64
in Windows, though you should probably use the portable uint64_t
), if that extends your range far enough.
Thanks to Joachim for a link to examples of C++11 enum usage: Strongly Typed Enums
Use smaller numbers. An enum can only be as big as a long. The size of a long depends on the compiler, but a typical size is either 32 or 64 bits. I see some 10 digit hex numbers there, those are too big.
User contributions licensed under CC BY-SA 3.0