использовать пользовательские Deleter
Проблема заключается в том, что unique_ptr<T>
должен вызвать деструктор T::~T()
в свой собственный деструктор, оператор назначения его перемещения и unique_ptr::reset()
функция-член (только). Однако они должны быть вызваны (неявно или явно) в нескольких ситуациях PIMPL (уже в деструкторе внешнего класса и операторе присваивания перемещения).
Как уже указывалось в другой ответ, один из способов избежать этого, чтобы переместить все операции, требующие unique_ptr::~unique_ptr()
, unique_ptr::operator=(unique_ptr&&)
и unique_ptr::reset()
в исходный файл, в котором фактически определен класс Pimpl помощник.
Однако это довольно неудобно и в какой-то степени бросает вызов самой точке идома. Это гораздо более чистое решение, которое позволяет избежать всего, что нужно для использования пользовательского deleter и только переместить его определение в исходный файл, в котором живет вспомогательный класс прыщей. Вот простой пример:
// file.h
class foo
{
struct pimpl;
struct pimpl_deleter { void operator()(pimpl*) const; };
std::unique_ptr<pimpl,pimpl_deleter> _pimpl;
public:
foo(some data);
foo(foo&&) = default; // no need to define this in file.cc
foo&operator=(foo&&) = default; // no need to define this in file.cc
//foo::~foo() auto-generated: no need to define this in file.cc
};
// file.cc
struct foo::pimpl
{
// lots of complicated code
};
void foo::pimpl_deleter::operator()(foo::pimpl*ptr) const { delete ptr; }
Вместо отдельного класса DeleteR, вы также можете использовать бесплатную функцию или static
члена foo
в сочетании с лямбда:
class foo {
struct pimpl;
static void delete_pimpl(pimpl*);
std::unique_ptr<pimpl,[](pimpl*p){delete_pimpl(p);}> _pimpl;
};
Сообщение полный код пожалуйста. Особенно конструкторы шаблонов. –
@daknok_t: библиотека интеллектуальных указателей boost запрещает 'boost :: unique_ptr' работать с неполными типами: вместо этого вам пришлось использовать' boost :: shared_ptr'. Вы уверены, что стандартная библиотека C++ не имеет такого же ограничения? – Hurkyl
@Alexandre: код, который OP размещен *, является * полным кодом для этого варианта использования. Файл, состоящий только из '#include', и эти две строки должны компилироваться ... при условии, что' unique_ptr' разрешено использовать с неполными типами. –
Hurkyl