I was advocating the use of a "polymorphic" design, where two structures that have the same initial member were aliased:
namespace Commands
{
enum Type { Foo };
}
struct Command
{
Commands::Type id;
};
struct Foo
{
Commands::Type id;
int value;
};
//e.g.
Foo foo = { Commands::Foo, 1337 };
Command* cmd = (Command*)&foo
switch( cmd->id )
{
case Commands::Foo:
Foo* fooCmd = (Foo*)cmd;
printf( "id = %d, value = %d\n", (int)fooCmd->id, fooCmd->value );
break;
}At the time, I thought this violated the strict-aliasing rule, but that the code would produce the intended behaviour anyway. The worst thing that I thought would happen, is that the compiler would generate code that redundantly reads "fooCmd->id", even though it already read "cmd->id" just above. However, the C++03 wording of the rule is:
If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:Does the bold statement mean that I'm not actually breaking the strict aliasing rule here, because the aliased value (i.e. id) is actually the correct type in both structures?
• the dynamic type of the object,
• a cv-qualified version of the dynamic type of the object,
• a type that is the signed or unsigned type corresponding to the dynamic type of the object,
• a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
• an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
• a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
• a char or unsigned char type.