I am trying to create a static container which has stack based memory and can hold N instances of T. Much alike std::vector I want currently unused memory to not contain initialized items of T. This is usually solved with placement new but that's not possible to use in constexpr.
Using unions I found a trick that you can use a union for this as follows:
template <typename value_type>
union container_storage_type
{
struct empty{};
constexpr container_storage_type(): uninitialized{}{}
constexpr container_storage_type(value_type v): value(v){}
constexpr void set(value_type v)
{
*this = literal_container_storage_type{v};
}
empty uninitialized;
value_type value;
};
This lets you store items uninitialized by setting the empty member and this works around the limitation that all members in constexpr have to be initialized.
Now the problem with this approach is that if value_typeis a type that implements operator=, the rule for unions says:
If a union contains a non-static data member with a non-trivial special member function (copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer.
This means that to be able to use this trick, I need to implement operator= in the union too, but how would that look?
constexpr container_storage_type& operator=(const container_storage_type& other)
{
value = other.value; //ATTEMPT #1
//*this = container_storage_type(other.value);ATTEMPT #2
return *this;
}
Attempt #1: This does not seem possible as the compiler complains that changing the active member of a union is simply disallowed in constant expressions.
Attempt #2: This works in the set() method from the previous snippet, as it doesn't change the active member per se, but reassigns the whole union. This trick seems unable to be used in the assignment operator however since that causes endless recursion...
Am I missing something here, or is this truly a dead end for using unions as a placement-new alternative in constexpr?
Are there other alternatives to placement new that I have completely missed?
https://godbolt.org/z/km0nTY Code that illustrates the problem