On Tue, Mar 21, 2017 at 2:22 PM, Richard Hodges via Boost < boost@lists.boost.org> wrote:
Here's a first cut of a polymorphic deleter (which at least allows you to spell the name of the unique_ptr<A> in the example). It's not optimally efficient, but a little SFO should do it.
#include <memory> #include <iostream>
namespace notstd {
class polymorphic_deleter { struct concept { virtual void impl_call() const = 0; };
template<class T, class Deleter> struct model final : concept { model(T *p, Deleter del) : p_(p) , del_(std::move(del)) {}
void impl_call() const { del_(p_); }
T *p_; Deleter del_; };
std::unique_ptr<concept> impl_;
template<class T, class Del> static auto make_model(T* p, Del&& del) { using deleter_type = std::decay_t<Del>; using pointer_type = T; return std::make_unique<model<pointer_type, deleter_type>> ( p, std::forward<Del>(del) ); };
public:
template<class T, class Del> polymorphic_deleter(T* p, Del&& del) : impl_(make_model(p, std::forward<Del>(del))) {}
void operator()(void*) const { impl_->impl_call(); }
};
template<class T, class...Args> auto make_polymorphic_unique(Args&&...args) { auto pt = std::make_unique<T>(std::forward<Args>(args)...); auto del = polymorphic_deleter(pt.get(), std::default_delete<T>()); return std::unique_ptr<T, polymorphic_deleter>(pt.release(), std::move(del)); };
}
struct A { ~A() { std::cout << "deleting A\n"; } };
struct B : A { ~B() { std::cout << "deleting B\n"; } };
int main() { auto pb = notstd::make_polymorphic_unique<B>(); auto pa = std::unique_ptr<A, notstd::polymorphic_deleter>( std::move(pb)); pa.reset(); }
Class `polymorphic_deleter` is implementation of the `function<void (void *)>` without small object optimization. Yes, it is possible to use unique_ptr with such deleter, but it requires additional memory allocation even for the case when deleter is std::default_delete. I have tried to avoid this. -- Andrey Davydov