I have a problem caused by breaking strict pointer aliasing rule. I have a type T
that comes from a template and some integral type Int
of the same size (as with sizeof
). My code essentially does the following:
T x = some_other_t;
if (*reinterpret_cast <Int*> (&x) == 0)
...
Because T
is some arbitary (other than the size restriction) type that could have a constructor, I cannot make a union of T
and Int
. (This is allowed only in C++0x only and isn't even supported by GCC yet).
Is there any way I could rewrite the above pseudocode to preserve functionality and avoid breaking strict aliasing rule? Note that this is a template, I cannot control T
or value of some_other_t
; the assignment and subsequent comparison do happen inside the templated code.
(For the record, the above code started breaking on GCC 4.5 if T
contains any bit fields.)
Why not simply:
(you may want to try to add also the
static
qualifier tozero
to see if it makes a difference performance-wise)Have you heard about
boost::optional
?I must admit I am unclear as to the real problem here... but boost::optional allow to store by value and yet know whether or not the actual memory has been initialized. I also allows in place construction and destruction, so could be a good fit I guess.
EDIT:
I think I finally grasped the problem: you want to be able to allocate a lot of objects, at various points in memory, and you'd like to know whether or not the memory at this point really holds an object or not.
Unfortunately your solution has a huge issue: it's incorrect. If ever
T
can somehow be represented by anull
bit pattern, then you'll think it's unitialized memory.You will have to resort yourself to add at least one bit of information. It's not much really, after all that's only 3% of growth (33 bits for 4 bytes).
You could for example use some mimick
boost::optional
but in an array fashion (to avoid the padding loss).Then it's as simple as that:
note: For simplicity's sake I have not considered the issue of alignment. If you don't know about the subject, read about it before fiddling with memory :)
Use a 33-bit computer. ;-P
On my system, GCC optimizes away both
is_T_0()
andmemcpy()
, resulting in just a few assembly instructions inmyfunc()
.It feels like a hack, but apparently I found a solution: using
volatile
forInt
casting. Essentially, what I am doing now is:The problem with bitfield
T
is now gone. Still, I don't feel quite happy about this asvolatile
is not well-defined in C++ AFAIK...How about this:
It might not be as efficient, but it should get rid of the warning.
ADDENDUM #1:
Since
T
is constrained to be the same size asInt
, make yourself a dummy bitwise zero value of typeT
and compare directly against it (instead of casting and comparing agaistInt(0)
).If your program is single-threaded, you could have something like this:
If it is multi-threaded, you'll want to avoid using a static member
zero_
, and have each container instance hold it's ownzero_
member:ADDENDUM #2:
Let me put the above addendum in another, simpler way: