Boost logo

Boost :

Subject: [boost] [smart_ptr] Is there any interest in unique_ptr with type erased deleter?
From: Andrey Davydov (andrey.a.davydov_at_[hidden])
Date: 2017-03-21 07:04:46

It is widely known that deleter type is part of std::unique_ptr type. It is
the most effective decision, but sometimes not very convenient. The most
important use cases (for me) when std::unique_ptr<T,
std::default_delete<T>> doesn't work are following:
1. unique_ptr to incomplete class
struct MyClass;
unique_ptr<MyClass> create();
auto ptr = create(); // compilation error

2. upcast to base without polymorphic destructor
struct Base
  // ...
  // no virtual ~Base() here
struct Derived : Base
  // ...
unique_ptr<Base> ptr = make_unique<Derived>(); // compiles by leaks!

3. unique_ptr with non-default deleter
unique_ptr<FILE, int (FILE *)> open_file(std::string const & path)
// works but looks ugly, why should the fact that fclose returns `int` be
visible from the signature of the function `open_path`?
  return { std::fopen(path, "r"), &std::fclose };

Of course, all this examples could be fixed if unique_ptr would be replaced
by shared_ptr, but the semantic of the shared ownership is not desirable
I have implemented smart pointer with semantics of unique ownership and
type erased deleter ( It has size of 3
pointers and it doesn't require additional memory allocations for the case
when deleter is empty class (for example, std::default_delete or
non-capturing lambda) and for the case when deleter is known at compile
time function (for instance, fclose). The are some simple examples of usage
and tests in the repo.

Why don't just use unique_ptr<T, function<void (void *>>? The main reason
is that due to the small object optimization std::function has rather big
size. For instance, sizeof(unique_ptr<T, function<void (void *>>) == 72 for
MSVC x64! Results for the other platforms can be found in the repo README.

Does it seem useful?

Andrey Davydov

Boost list run by bdawes at, gregod at, cpdaniel at, john at