I've created some templates in order to create aligned-storage capable of being used for placement-new:
template<typename T, typename... U>
constexpr size_t max_alignof()
{
if constexpr (sizeof...(U))
return std::max(alignof(T), max_alignof<U...>());
else
return alignof(T);
}
template<typename T, typename... U>
constexpr size_t max_sizeof()
{
if constexpr (sizeof...(U))
return std::max(sizeof(T), max_sizeof<U...>());
else
return sizeof(T);
}
// This isn't allowed by the standard, but illustrates my goal
template <typename... T>
using aligned_buffer_t = alignas(max_alignof<T...>()) char[max_sizeof<T...>()];
// Types A, B are classes that I want to placement-new
aligned_buffer_t<A, B> buffer;
A* = new (&buffer[0]) A();
A->~A();
B* = new (&buffer[0]) B();
B->~B();
How can I accomplish the above, without having to re-type the template parameters to aligned_buffer_t
? The best solution I could come up with to accomplish this was the following macro:
#define ALIGNED_BUFFER_T(VAR, ...)\
alignas(max_alignof<__VA_ARGS__>()) char VAR[max_sizeof<__VA_ARGS__>()]
ALIGNED_BUFFER_T(buffer, A, B);
Is the above possible without using macros, and without using the deprecated std::aligned_storage
? The reason I am interested is because one of the class lists is auto-generated, so the code I tried to write was:
aligned_buffer_t<
#include "GeneratedClassList.hpp"
> buffer;
I couldn't figure out any syntax using macros that would enable such a construct.
As pointed out by ALX23z, my proposed approach was just a roundabout way of reimplementing std::variant
. The solution therefore is simply to change the code to:
std::variant<std::monostate, A, B> buffer;
A *a = &buffer.emplace<A>();
// Do stuff with a
B *b = &buffer.emplace<B>();
// Do stuff with b