2

I'm compiling code that was written for GCC, in Visual C++ 2012. I'm getting warnings thrown about enum value truncation with the following enum (due to the value being outside the range of an int):

enum tile_flags { TILE_FLAG_INNER_FLAME= 0x10000000ULL, TILE_FLAG_CONSTRICTED= 0x20000000ULL, TILE_FLAG_MIMIC_INEPT 0x2000000000ULL TILE_FLAG_MIMIC 0x4000000000ULL TILE_FLAG_MIMIC_RAVEN 0x6000000000ULL TILE_FLAG_MIMIC_MASK 0x6000000000ULL } 

When compiling for x86, it would appear MSVC simply truncates the enum values to fit in 32bits. However, no truncation occurs in GCC. What is happening on GCC? And how can I make this work for MSVC?

2 Answers 2

10

From N3485, § 7.2/6:

For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration. If no integral type can represent all the enumerator values, the enumeration is ill-formed. It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int. If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.

Therefore, if MSVC has the necessary long long support, it should make that the underlying type anyway. Seeing as how it doesn't, there's one thing you can try in order to coax it.

Specify the underlying type:

enum tile_flags : unsigned long long { ... }; 
Sign up to request clarification or add additional context in comments.

10 Comments

Wow, did not know you could do this! Is there still type safety with the type tile_flags, or does the compiler treat it as an unsigned long long in this case?
@RandyGaul, Yes, it's still a distinct type. It just uses unsigned long longs to store the values. This is a C++11 feature. You can also have scoped enums, which force you to use EnumName::Value and don't implicitly convert to integers.
If you want type safety with enums, look at enum classes from C++11, without them, enums are not really type safe.
Although that quote isn't (or at least shouldn't be) relevant for an unscoped enumeration like this, which should choose an underlying type large enough for all the values as described in 7.2/6. Unfortunately, it sounds like Microsoft got that wrong.
@MikeSeymour, Oops, I do have a slight memory of it being different for scoped and unscoped enums. I'll go looking again.
|
0

If you need more entries than an unsigned long long can get you, try using a struct:

struct tile_flags { bool innerFlame : 1; bool constricted : 1; bool mimicInept : 1; bool mimic : 1; // etc }; 

This uses a bitfield, which usually means that the values will be packed as tightly as possible, and while it can make construction a bit more difficult than traditional flag numbers, its your easiest option for more than sizeof unsigned long long bits.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.