Consider the following class:

template <class T>
class defer {
public:
    template <class ...Args>
    void construct(Args&&...);
    T& obj();
    ~defer();
private:
    std::uint8_t memory[sizeof(T)];
    T * ptr();
};

template <class T>
template <class ...Args>
void defer<T>::construct(Args&& ...args) {
    new(static_cast<void*>(&memory[0])) T(std::forward<Args>(args)...);
}

template <class T>
T& defer<T>::obj() {
    return *(ptr());
}

template <class T>
defer<T>::~defer() {
    ptr()->~T();
}

template <class T>
T * defer<T>::ptr() {
    return static_cast<T*>(&memory[0]);
}

NOW I KNOW that there are issues with this, but in order to make the code short for purposes of discussion we are going to assume that the defer::construct() is always called before the object goes out of scope.

That being said, is it always necessarily safe to do this? Or can in some weird corner case of multiple virtual inheritance with other craziness can std::uint8_t[sizeof(T)] not allocate enough space?

有帮助吗?

解决方案

R. Martinho Fernandes beat me to it! Use

typename std::aligned_storage<sizeof(T)>::type  memory;

and you're good to go. See here for details.


As our panel of commentators has pointed out, the default alignment is always enough, but may be more stringent than required for your type (so you waste space with extra padding). You can avoid this by just specifying it explicitly:

typename std::aligned_storage<sizeof(T), alignof(T)>::type memory;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top