Search code examples
c++option-typereinterpret-caststrict-aliasingtype-punning

custom optional breaks strict aliasing rules


I wrote a custom optional class (since I am forced to use C++98 without STL). It looks like this:

template <typename T>
struct optional {
    char value[sizeof(T)];
    bool has_value;

    T& operator*() {
        return *reinterpret_cast<T*>(value);
    }
};

The compiler produces the warning dereferencing type-punned pointer will break strict aliasing rules.

What can I do to make this class without UB? Maybe memcpy should be used, but I don't understand how.


Solution

  • What can I do to make this class without UB?

    • Use placement-new to create the object.
    • Call the destructor of the created object in destructor of optional
    • Do not reinterpret the address of the storage. Use the pointer returned from placement new. This unfortunately means that you need to store the pointer as a member. You can replace the bool since null pointer would signify empty state.
    • Take care of alignment. This can be quite tricky pre-C++11. You may need to rely on non-standard language features to achieve this. Given a pointer member which has quite strict alignment, and the fact that C++98 has no overaligned types, you might get away with ignoring alignment for most types.

    It would be much easier to allocate the object dynamically. Slower, very likely. But simpler and standard conformant.