zzy
zzy

Reputation: 791

How to set the deleter for an existing shared pointer?

I need to write my own destructor for a shared pointer instance. Unfortunately, such instance is acquired from a library function call and it's not I that initialize it. So how can I "set" the destructor here?

Ideally, the code in my mind may look like

pointer.setDeleter(myDeleter);

or

pointer = std::make_shared<MyType>(pointerOld.get(), myDeleter);

I didn't find the API for the first assumption. For the second one, it is said that MyType doesn't have a constructor with 2 parameters. It is not compilable.

Any ideas for this?

Thanks!

Upvotes: 1

Views: 529

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275395

This is the closest I can get.

template<class T>
std::shared_ptr<T> extra_deleter( std::shared_ptr<T> in, std::function<void(T*)> action ) {
  if (!in) return {};
  if (!action) return std::move(in);
  // action=std::move(action) in c++14
  auto new_deleter = [action](std::shared_ptr<T>* tin) { 
      action(tin->get());
      delete tin;
    };

  auto tmp = std::shared_ptr<std::shared_ptr<T>>(
    new shared_ptr<T>(std::move(in)),
    std::move(new_deleter)
  );
  if (!tmp) return {};
  // aliasing ctor:
  return {tmp, tmp.get()->get()};
}

this create a shared pointer shared pointer, augments it with a custom deleter action, then uses the aliasing ctor to create a shared pointer to T.

This does not cause extra code to run when the source shared_ptr is destroyed. Instead it creates a new shared_ptr with extra destruction code in it. When the new lineage of shared_ptr dies, the action is run.

If there are no other references to the original shared_ptr state remaining, then the original destroyer of the shared_ptr runs.

Upvotes: 1

Related Questions