Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying a Deleter for std::shared_ptr that works on all objects of a particular type or its derived types

I have the following classes in my project

class Base
{
    public:
    virtual ~Base(){};
}

class Der1: public Base
{
    public:
    virtual ~Der1(){};
}

class Der2: public Base
{
    public:
    virtual ~Der2(){};
}

I am holding the objects of these classes as std::shared_ptr. I need to provide a custom deleter for all the objects that are either of type Base or any of its derived types.

The code I want in the deleter method will be doing the same thing for all these object, say

class Deleter
{
    public:
    void operator()( Base * b )
    {
        //Do something
        delete b;
    }
}

Instead of providing the deleter during the construction of each objects like

std::shared_ptr< Der1 > pDer1( new Der1(), Deleter() );
std::shared_ptr< Der2 > pDer2( new Der2(), Deleter() );

Is there a way to specify something like "for all the shared pointers to objects of type Base or its derived types use Deleter for deletion? As deleter class is just taken in the constructor of shared_ptr how can someone specify a deleter for a particular type?

like image 881
sajas Avatar asked Mar 15 '23 22:03

sajas


1 Answers

I'd write a creation/factory function in Base, returning the shared_ptr for the correct derived type. Something to this effect:

class Base
{
  //...public...
  template <class Derived>
  static std::shared_ptr<Base> create()
  {
    return std::shared_ptr<Base>(new Derived, Deleter());
  }
};

EDIT: Function needs to be static...

If derived has more than one parameter, that can be solved with variadic templates and perfect forwarding.

EDIT:

Like this (For more than one parameter derived constructor):

#include <iostream>
#include <memory>

struct Base;

struct Deleter
{
    void operator()(Base* b);
};

struct Base
{
  //...public...
  template <class Derived, class ... Args>
  static std::shared_ptr<Base> create(Args&&... args)
  {
    return std::shared_ptr<Base>(new Derived(std::forward<Args>(args)...), Deleter());
  }
  virtual ~Base(){}
};

void Deleter::operator()(Base* b){ delete b; }


struct Derived : Base
{
  Derived(int a, int b, int c)
  {
  }
};

int main() {
    std::shared_ptr<Base> p = Base::create<Derived>(1,2,3);
    return 0;
}
like image 123
Werner Erasmus Avatar answered Apr 08 '23 08:04

Werner Erasmus