Jeff M Jeff M - 2 months ago 9
C++ Question

unique/shared_ptr with custom operator=

I'm working with a polymorphic type (that is, I always interact with it through a pointer) that has methods "Destroy()" and "Clone()", and I would like to wrap it in a resource safe type.

Now, if "Destroy()" was all I had to worry about, then I could use unique_ptr with a custom deleter and it would be easy. But, this resource handle type is used as a member in another type that is otherwise copyable using default generated copy and assign operations. Ideally, I would like to customize the resource handle's copy constructor and assignment to invoke "Clone()", just like I already customize the resource handle's destructor to invoke "Destroy()". But looking through the docs on unique_ptr and shared_ptr, I don't see anything that would let me do that.


  1. Did I miss something in the docs? Is there a ready-made std way to do this?

  2. If not, should I extend unique_ptr and override the copy operations?

  3. Alternatively, should I just write my own resource handle with all the usual pointer semantics from scratch?


Answer

You may create wrapper around std::unique_ptr

// To handle your cusstom Destroy
struct DestroyDeleter
{
     void operator(Interface* o) {
         object->Destroy();
         delete object;
     }
};

using InterfacePtr = std::unique_ptr<Interface, DestroyDeleter>;

// To handle the copy with clone:
class wrapper
{
public:
    explicit wrapper(InterfacePtr o) : data(std::move(o)) {}

    wrapper(const wrapper& rhs) : data(rhs.data->Clone()) {}
    wrapper(wrapper&& rhs) = default;

    wrapper& operator =(const wrapper& rhs) { data = rhs.data->Clone(); }
    wrapper& operator =(wrapper&& rhs) = default;

    const Interface* operator ->() const { return data.get(); }
    Interface* operator ->() { return data.get(); }

    const Interface& operator *() const { return data; }
    Interface& operator *() { return *data; }

private:
    InterfacePtr data;
};