Я написал эту статью и получил некоторые комментарии по этому поводу, которые смутили меня.
В основном это сводится к тому, что я видел, что T2 используется только как параметр шаблона и ошибочно подскочил к выводу, что поэтому я мог бы воспользоваться возможностью объявления вперед:
struct T2;
struct T1
{
std::auto_ptr<T2> obj;
};
Это вызывает UB, если я не буду определять T2 где-то в одном TU, потому что std::auto_ptr<T2> вызывает delete на своей внутренней T2* и вызов delete указателя на объект неполного типа, полный тип которого имеет нетривиальный деструктор undefined:
[C++11: 5.3.5/5]:Если удаляемый объект имеет неполный тип класса в точке удаления, а полный класс имеет нетривиальный деструктор или функцию освобождения, поведение undefined.
Инструментарий GCC, с которым я столкнулся, использовал — v4.3.3 (Sourcery g++ Lite 2009q1-203) — был достаточно любезен, чтобы сообщить мне с примечанием:
note: ни деструктор, ни оператор-оператор класса не будут вызваны, даже если они объявлены при определении класса.
хотя, похоже, трудно получить эту диагностику в других версиях GCC.
Моя проблема заключалась в том, что было бы намного легче обнаружить такую ошибку, если бы delete указатель на экземпляр неполного типа был плохо сформирован, а не UB, но это похоже на неразрешимую проблему для для решения, поэтому я понимаю, почему это UB.
Но потом мне сказали, что если бы я использовал std::unique_ptr<T2>, это было бы безопасно и совместимо.
n3035 якобы говорит в 20.9.10.2:
Параметр шаблона
Tofunique_ptrможет быть неполным.
Все, что я могу найти в С++ 11, это:
[C++11: 20.7.1.1.1]:/1 Шаблон класса
default_deleteиспользуется как дефолт по умолчанию (политика уничтожения) для шаблона классаunique_ptr./2 Параметр шаблона
Tofdefault_deleteможет быть неполным.
Но для default_delete operator() требуется полный тип:
[C++11: 20.7.1.1.2/4]:ЕслиTявляется неполным, программа плохо сформирована.
Я полагаю, что мой вопрос таков:
Являются ли комментаторы моей статьи правильными, говоря, что единица перевода, состоящая только из следующего кода, хорошо сформирована и четко определена? Или они ошибаются?
struct T2;
struct T1
{
std::unique_ptr<T2> obj;
};
Если они верны, как ожидается, что компилятор выполнит это, учитывая, что есть веские причины для того, чтобы быть UB, по крайней мере, когда используется std::auto_ptr?