Search code examples
c++unique-ptr

Overriding the deleter of unique_ptr


I have the following code in C++

#include <iostream>
#include <memory>

class MyType{
public:
    ~MyType() {
    std::cout<<"Destructor called";
    }
};

template<typename T>
struct deleter
{
    deleter(void)  {}

    template<typename U>
    deleter(deleter<U> const&, std::enable_if_t<std::is_convertible<U*, T*>::value>* = nullptr) {}

    virtual void operator()(T* p) const 
    {
        std::cout<<"deleter called";
        static_assert(sizeof(T) > 0, "");
        if (p)
        {
            p->~T();
            free(const_cast<std::remove_const_t<T>*>(p));
        }
    }
};


template<typename T>
struct null_deleter : public deleter<T> {
    void operator()(T* ptr) const override {
        // Do nothing
        std::cout<<"null deleter called";
    }
};


template<typename T>
using unique_ptr = std::unique_ptr<T, deleter<T>>;
 
int main()
{
    MyType myType;
    std::cout<<"hello";

    unique_ptr<MyType> u(&myType);
    //unique_ptr<MyType> u(&myType, null_deleter<MyType>());
    u.get_deleter() = null_deleter<MyType>();
    return 0;
}

I have the requirement where I need to override the behaviour of unique_ptr declared as using unique_ptr = std::unique_ptr<T, deleter<T>>; to do nothing. So, I extended deleter and overrode the operator() . But I am getting below error in my program:

Program returned: 139
Program stderr
free(): invalid pointer

Why the program still calls deleter<T> instead of null_deleter<T>. Is there any way to override the behaviour of unique_ptr's deleter?


Solution

  • This doesn't work because of slicing. What you do when you assign to get_deleter() is copy the deleter<T> portion of your object:

    Deleter& get_deleter() noexcept;
    

    The carried deleter will always be of static and dynamic type deleter<T>. Never, of null_deleter<T> if your have an std::unique_ptr<T, delter<T>>.

    You cannot change that afterwards.