пятница, 20 февраля 2026 г.

[prog.c++] Дошел до чистого безумия: new(this) another_object_type

Тяжкая судьба C++программиста довела использования в коде трюка, про который еще несколько лет назад и вовсе не знал. Речь про замену типа объекта через вызов placement new внутри метода самого заменяемого объекта.

В моем случае получился код вроде вот такого:

templatetypename ValueT >
void
special_map< ValueT >::fixed_capacity_node::insert_item( ValueT value )
{
   auto & self = this->self_data();
   if( self.size() < self.capacity() )
   {
      ... // use the existing node.
   }
   else
   {
      ... // prepare internal data for a new node type.

      // Replace the node by an instance of the new type.
      new(this) dynamic_capacity_node{ std::move(new_node_internal_data) };
   }
}

Т.е. есть объект типа fixed_capacity_node в котором имеется контейнер для небольшого количества элементов. При вставке очередного элемента может оказаться, что этот контейнер исчерпан и нужно перейти к использованию dynamic_capacity_node вместо fixed_capacity_node. Для чего новый объект dynamic_capacity_node и создается. Но не просто так, а в той области памяти, которую только что занимал старый fixed_capacity_node объект.

Еще несколько лет назад мне и в голову не приходило, что такое возможно. Однако, когда изучал тему std::launder, то наткнулся на подобный трюк. И вот теперь сам дошел до его применения.

PS. Никому не советую повторять подобное в домашних условиях. Как говорится, все показанное было выполнено специально подготовленными профессионалами 😎 Были предприняты различные предохранительные меры дабы удостоверится, что fixed_capacty_node и dynamic_capacity_node идентичны и по размеру, и по выравниваю. И что после смены типа объекта никто не обращался к нему по старому указателю без std::launder.