Когда тип считается завершенным?

Рассмотрим следующий фрагмент кода. Деструктор boost::scoped_ptr вызывается в конце основной функции. Деструктор использует boost::checked_delete для освобождения инкапсулированного указателя виджета.

#include <boost/scoped_ptr.hpp>
#include <iostream>

class Widget;
Widget *make_widget();

int main()
{  
  boost::scoped_ptr<Widget> sp(make_widget());
  // std::cout << sizeof(Widget) << std::endl;
}

class Widget
{
public:
  Widget() {}
  ~Widget() { std::cout << "Widget destructor called." << std::endl; }
};

Widget *make_widget()
{
  return new Widget;
}

Я ожидал, что этот код не сможет скомпилироваться, так как класс Widget неполон в момент, когда деструктор scoped_ptr<Widget> вызывается. Однако это компилируется чисто на g++ 4.8 и Visual Studio 2010. Обратите внимание на закомментированный оператор с sizeof(Widget) Выражение в основной функции. Если я раскомментирую его, он не будет компилироваться, подразумевая, что Widget должно быть неполным в этой точке.

Каково правильное объяснение этого поведения?

РЕДАКТИРОВАТЬ: Некоторые ответы (в настоящее время удалены) указали на неопределенное поведение, но я ожидал бы использование check_delete в scoped_ptrдеструктор, чтобы вызвать сбой компиляции. FWIW, я использую Boost 1.55.

1 ответ

5.3.5 Удалить [expr.delete]

5 Если удаляемый объект имеет неполный тип класса в точке удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения, поведение не определено.

Таким образом, вы, конечно, ожидаете, что это будет UB, так как Widget::~Widget() является нетривиальным, и вы ожидаете, что безопасный буст в форсированном режиме выдает ошибку.

Теперь давайте копать выше:

2.2 Фазы перевода [lex.phases]

8 Переведенные единицы перевода и единицы создания экземпляров объединяются следующим образом: [Примечание: ... ] Каждая переведенная единица перевода проверяется для составления списка необходимых экземпляров. [Примечание: это может включать в себя экземпляры, которые были явно запрошены (14.7.2). - примечание] Определения необходимых шаблонов находятся. Это зависит от реализации, должен ли быть доступен источник блоков перевода, содержащих эти определения. [Примечание: реализация может закодировать достаточную информацию в переведенную единицу перевода, чтобы гарантировать, что источник здесь не требуется. —Конец примечания] Все необходимые экземпляры выполняются для создания единиц реализации. [Примечание: они похожи на переведенные единицы перевода, но не содержат ссылок на необоснованные шаблоны и определения шаблонов. - примечание] Программа плохо сформирована, если какая-либо инстанция не удалась.

Вы сохранены фазами перевода:
Переведите модуль перевода, затем создайте шаблоны...

Другие вопросы по тегам