Take the 2-minute tour ×

Consider the following class:

template <class T>
class defer {
    template <class ...Args>
    void construct(Args&&...);
    T& obj();
    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() {

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?

share|improve this question
std::uint8_t[sizeof(T)] will always have enough space. But... it may not always have the right alignment (std::aligned_storage can help there). –  R. Martinho Fernandes Oct 25 '12 at 15:50
uint8_t is optional. Use uint_least8_t or uint_fast8_t; they will always exist. –  Pete Becker Oct 25 '12 at 17:04
@Pete Becker: Yes, but do you know of any platforms that do not have 8-bit integral types? Also, I know that on some platforms uint_least8_t and uint_fast8_t are both typedefs to int for efficiency purposes, which could mean a 300% memory overhead. std::uint8_least8_t[sizeof(T)/sizeof(std::uint_least8_t)+((sizeof(T) % sizeof(std::uint_least8_t) != 0) ? 1 : 0)] works, but is a tad ugly for my taste... –  Robert Mason Oct 25 '12 at 17:19
uint_least8_t is required to be a synonym for an unsigned type with at least 8 bits "such that no unsigned type with lesser size has at least the specified width". (C standard, If your implementation defines it as int when there are smaller types available, it not only has the wrong properties (because it's a signed type), but it's too big, hence doesn't conform to the standard. –  Pete Becker Oct 25 '12 at 17:38
As to non-8-bit systems, see stackoverflow.com/questions/5516044/system-where-1-byte-8-bit. –  Pete Becker Oct 25 '12 at 17:41
show 1 more comment

1 Answer

up vote 12 down vote accepted

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;
share|improve this answer
Haha, for a moment there you made the usual mistake of forgetting ::type :P –  R. Martinho Fernandes Oct 25 '12 at 15:53
you caught me ;D –  Useless Oct 25 '12 at 15:54
What about aligned_storage<sizeof(T),alignof(T)> ? Not a big deal, but might save padding in the case where T doesn't need the default (maximum) alignment. –  Steve Jessop Oct 25 '12 at 16:14
The default alignment is "the most stringent alignment requirement for any C++ object type whose size is no greater than" the called-for length. Similar to the alignment requirements when allocating a char array. In some cases you don't need such a strict alignment; e.g. if T is int[2] then you only need alignment for an int, but the default-alignment would be sufficient for any object of twice that size. –  bames53 Oct 25 '12 at 16:22
Cheers - fixed the alignment description. –  Useless Oct 25 '12 at 16:28
show 4 more comments

Your Answer


