Сначала прочитал посты Herb's Sutters GotW, касающиеся pimpl в C++11:
У меня некоторые проблемы с пониманием решения, предложенного в GotW #101. Насколько я могу понять, все проблемы, с трудом решенные в GotW #100, вернулись с новой силой:
Члены pimpl
являются внестрочными шаблонами, и их определения не видны в месте использования (в определении класса class widget
и неявно сгенерированных специальных функциях-членах widget
). Явных инстанцирований также нет. Это приведет к неразрешенным внешним ошибкам при компоновке.
widget::impl
все еще неполный в точке, где pimpl<:impl>::~pimpl()
является инстанцированным определением (я не думаю, что он вообще инстанцирован, просто на него ссылаются). Поэтому std::unique_ptr<:impl>::~unique_ptr()
вызывает delete
на указателе на неполный тип, что приводит к неопределенному поведению, если widget::impl
имеет нетривиальный деструктор.
Пожалуйста, объясните, что заставляет компилятор генерировать специальные члены в контексте, когда widget::impl
является полным. Потому что я не могу понять, как это работает.
Если GotW #101 все еще требует явного определения widget::~widget()
в файле реализации, где widget::impl
является полным, то, пожалуйста, объясните комментарий "More Robust" (который @sehe процитировал в своем ответе).
Я смотрю на основное утверждение GotW #101 о том, что обертка "устраняет некоторые части boilerplate", что, как мне кажется (основываясь на остальной части параграфа), означает объявление и определение widget::~widget()
. Так что, пожалуйста, не полагайтесь на это в своем ответе, в GotW #101 этого нет!
Херб, если ты заглянешь, пожалуйста, сообщи мне, можно ли вырезать и вставить код решения сюда для справки.