Reputation: 15715
dereferencing type-punned
I have an enum
enum AgentStatus { kSTOPPED = 0, kRUNNING, kIDLE, kNAGENTSTATUS };
I need to pass it to a function of an external library with many overloaded variants. I want to pass it to the second argument:
DimService::DimService(const char*, int&);
DimService::DimService(const char*, char*);
...
If I do a cast to (int&) of my enum variable, I get the infamous warning :
warning: dereferencing type-punned pointer will break strict-aliasing rules
If I do a cast to (int) I get this
invalid conversion from ‘int’ to ‘char*’
error: initializing argument 2 of ‘DimService::DimService(const char*, char*)’
What is the correct way ?
Upvotes: 7
Views: 4658
Reputation:
The answer from Bill is the correct answer technically.
1) Another approach
Another way to do this if you need to get rid of the enum-ness of the type is to make the type an int itself.
typedef int MyEnum;
enum
{
CONST1 = 0,
etc...
};
And then just use it like normal. The compiler will not catch bad assignments of values, but since you can tag all the declarations as MyEnum type it should be simple enough to follow what is happening, and you can just pass the variables anywhere that it says int.
2) Dangerous approach
NEVER DO THIS!
EnumType v = EnumValue_...
MyFunction( *((int*)&v) );
OR THIS...
#define MAKE_INT_REF(v) *((int*)&(v))
MyFunction( MAKE_INT_REF(v) );
The reason is because the compiler can automatically choose the type to use for the enum. It might choose int or it might choose char. You can not be sure across different compilers and platforms. So if you try casting an enum you will end up with unportable code and also very dangerous code, because writing back to such a cast can overwrite other values.
Upvotes: 7
Reputation: 14685
When you have trouble with an in-line cast it can be helpful to break it out as a separate line:
const AgentStatus enumValue = kRUNNING;
...
int intValue = static_cast<int>(enumValue);
DimService("works now", intValue);
Upvotes: 8