Я написал эту статью и получил некоторые комментарии по этому поводу, которые смутили меня.
В основном это сводится к тому, что я видел, что 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:
Параметр шаблона
T
ofunique_ptr
может быть неполным.
Все, что я могу найти в С++ 11, это:
[C++11: 20.7.1.1.1]:
/1 Шаблон класса
default_delete
используется как дефолт по умолчанию (политика уничтожения) для шаблона классаunique_ptr
./2 Параметр шаблона
T
ofdefault_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
?