Do the following class break the strict aliasing rule:
template<typename T>
class store {
char m_data[sizeof(T)];
bool m_init;
public:
store() : m_init(false) {}
store(const T &t) : init(true) {
new(m_data) T(t);
}
~store() {
if(m_init) {
get()->~T();
}
}
store &operator=(const store &s) {
if(m_init) {
get()->~T();
}
if(s.m_init) {
new(m_data) T(*s.get());
}
m_init = s.m_init;
}
T *get() {
if (m_init) {
return reinterpret_cast<T *>(m_data);
} else {
return NULL;
}
}
}
My reading of a standard is that it is incorrect but I am not sure (my usage is to have an array of objects T + some metadata of those objects but to have control over the object construction/deconstruction without manually allocating memory) as the allocated objects are used as examples for placement new in standard.
The standard contains this note:
And aligned_storage is defined in part with:
The only property covered by the standard that restricts the addresses at which an object can be constructed is alignment. An implementation might have some other restrictions, however I’m not familiar with any that do. So just ensure that having correct alignment is enough on your implementation and I think this should be okay. (and in pre-C++11 compilers you can use use compiler extensions for setting alignment such as
__attribute__((alignment(X)))or__declspec(align(X)).I believe that as long as you don’t access the underlying storage directly the aliasing rules don’t even come into the picture, because the aliasing rules cover when it is okay to access the value of an object through an object of a different type. Constructing an object and accessing only that object doesn’t involve accessing the object’s value through an object of any other type.
Earlier answer
The aliasing rules specifically allow char arrays to alias other objects.
You do need to make sure that the array is properly aligned for type T though.
The above is C++11 syntax for setting alignment, but if you’re on a C++03 compiler then you’ll need a compiler specific attribute to do the same thing. GCC has
__attribute__((aligned(32)))and MSVC has__declspec(align(32))Kerrek SB brings up a good point that the aliasing rules state that it’s okay to access the value of a T object via a char array, but that may not mean that accessing the value of a char array via a T object is okay. However, if the placement new expression is well defined then that creates a T object which I think it’s okay to accesses as a T object by definition, and reading the original char array is accessing the value of the created T object, which is covered under the aliasing rules.
I think that implies that you could store a T object in, for example, an int array, and as long as you don’t access the value of that T object through the original int array then you’re not hitting undefined behavior.