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?
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.