The question relates to this post.
Some authoritative users stated that the following code breaks strict aliasing rules.
#include <boost/static_assert.hpp>
template <typename T>
struct MyType {
private:
T data;
public:
template <typename U>
operator U () {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to convert to data type of different size");
return *((U*) &data);
}
template <typename U>
NeonVectorType<T>& operator =(const U& in) {
BOOST_STATIC_ASSERT_MSG(sizeof(U) == sizeof(T),"Trying to copy from data type of different size");
data = *((T*) &in);
return *this;
}
}
However, I am never using a pointer to write data, and I am never sharing a pointer to it, so I cannot see how value contained in a variable can change without the compiler realizing that this is happening. My impression is that maybe I am breaking some rules, but not the strict aliasing ones...
Note: I don't know how much this matters, but my compiler (gcc 4.9) does not issue warnings.
*((U*) &data)
will violate strict aliasing if this is areinterpret_cast
and the typeU
is not permitted to alias the typeT
. The permitted types appear in this list.The rule refers to both reading and writing.
Here is a good article that explains some of the rationale behind the rules.
As noted on the main strict aliasing thread, you can use
memcpy
as work around , for example:and in the other function
Note that raw byte copies of class types are subject to some restrictions (I think the classes have to be POD, and you'd better be sure they have the same layout).
The language in the standard is more general than this; [basic.life]/7 has:
In your
operator=
you're using an lvalue of typeT
to write todata
, and inoperator U
you're using a pointer of typeU
to read it; whereU
andT
are unrelated and not character types this is UB.Just use
memcpy
. It's guaranteed to work, and it's efficient (try it)!