Из документации объединения :
Если объединение содержит нестатический элемент данных с нетривиальной специальной функцией-членом (конструктор копирования / перемещения, копирование / перемещениеприсваивание или деструктор), эта функция по умолчанию удаляется в объединении и должна быть явно определена программистом.
Это правило имеет большой смысл, если вы помнитечто C ++ не отслеживает активный член объединения , поэтому, когда объединение разрушается, он не знает, деструктор какого члена вызывать. Конечно, если все члены имеют тривиальные деструкторы, это не имеет значения.
Из документации _COM_SMARTPTR_TYPEDEF :
На умный указатель обычно ссылается typedefопределение, предоставленное макросом _COM_SMARTPTR_TYPEDEF. Этот макрос берет имя интерфейса и IID и объявляет специализацию _com_ptr_t с именем интерфейса плюс суффикс Ptr.
Из источников _com_ptr_t:
// If we still have an interface then Release() it. The interface
// may be NULL if Detach() has previously been called, or if it was
// never set.
//
~_com_ptr_t() throw()
{
_Release();
}
Как видите, _com_ptr_t
имеет нетривиальный деструктор, поэтому вам нужно добавить явный деструктор в ваше объединение. Это одна из редких ситуаций, когда вам нужно вручную вызывать деструкторы на объектах. Примерно так:
union TextureData
{
ID3D11Texture2DPtr m_tex2D;
BYTE* m_byte;
~TextureData() {
if (/* m_tex2D is the active member */)
m_tex2D.~_com_ptr_t();
}
};
Обратите внимание, что поскольку TextureData
не отслеживает своего активного участника, вам необходимо определить, активен ли m_text2D
или нет самостоятельно.
Другой подход к вамможно использовать это использовать std::variant
вместо необработанного объединения. В отличие от объединения, вариант действительно отслеживает активного участника («альтернатива») и вызывает соответствующий деструктор для вас.