Я пытаюсь создать статический контейнер, который имеет основанную на стеке память и может содержать N экземпляров T. Очень похоже std::vector
Я хочу, чтобы в настоящее время неиспользуемая память не содержала инициализированные элементы T. Это обычно решается с размещением нового, но это невозможно использовать в constexpr.
Использование союзов
Я нашел трюк, что вы можете использовать союз для этого следующим образом:
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;
};
Это позволяет хранить элементы неинициализированными, устанавливая элемент empty
, и это работает вокруг ограничения, что все члены в constexpr должны быть инициализированы.
Теперь проблема этого подхода заключается в том, что если value_type
- это тип, который реализует operator=
, то правило для профсоюзов гласит: :
Если объединение содержит нестатический элемент данных с нетривиальной специальной функцией-членом (конструктор копирования / перемещения, назначение копирования / перемещения или деструктор), эта функция по умолчанию удаляется в объединении и ее необходимо определить явно программистом.
Это означает, что для того, чтобы использовать этот трюк, мне нужно также реализовать operator=
в объединении, но как это будет выглядеть?
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;
}
Попытка # 1: Это не представляется возможным, так как компилятор жалуется, что изменение активного члена объединения просто запрещено в константных выражениях.
Попытка № 2: Это работает в методе set()
из предыдущего фрагмента, так как он не изменяет активный элемент как таковой, но переназначает весь союз. Этот трюк, похоже, не может быть использован в операторе присваивания, поскольку он вызывает бесконечную рекурсию ...
Я что-то здесь упускаю или это действительно тупик для использования профсоюзов в качестве альтернативы размещения в constexpr?
Есть ли другие варианты размещения новых, которые я полностью пропустил?
https://godbolt.org/z/km0nTY Код, иллюстрирующий проблему