I would like to use unique_ptr with my deleter. I would like my unique_ptr with my deleter to be fully compatible with unique_ptr with default deleter.
I did so:
template <typename T>
struct QObjectDeleteLaterDeletor :
public std::default_delete<T>
{
void operator()(T *p)
{
p->deleteLater();
}
};
template <typename T, class... Args>
std::unique_ptr<T> qtMakeUniqueSpecial(Args&&... args)
{
return std::unique_ptr<T>(
new T(std::forward<Args>(args)...),
QObjectDeleteLaterDeletor<T>());
}
This compiles, but does not work. My custom deleter ignored and default one used instead as if I did not specify it at all.
I need all of this to be possible to do things like that:
auto ptr1 = qtMakeUniqueSpecial<MyObject>();
std::unique_ptr<MyObject> ptr2;
ptr2 = std::move(ptr1);
Please note that now even ptr1.reset() will lead to calling the standard deleter, not my one.
Is it even possible?
You need specify QObjectDeleteLaterDeletor
as the template argument; otherwise, std::default_delete
will be used as the deleter, which is slicing-copied from QObjectDeleteLaterDeletor
.
template <typename T, class... Args>
std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> qtMakeUniqueSpecial(Args&&... args)
{
return std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> (
new T(std::forward<Args>(args)...),
QObjectDeleteLaterDeletor<T>());
}
Note that you declare ptr2
as std::unique_ptr<MyObject>
, then ptr2
will destroy the pointer by std::default_delete
. If you declare its type accord with ptr1
like auto ptr2 = std::move(ptr1);
then it'll be fine.
You're trying to use
namespace std {
template<typename T, typename Deleter = default_delete<T> >
class unique_ptr;
}
which has a second template argument Deleter
. Failing to specify that, it defaults to std::default_delete<T>
. Your code
std::unique_ptr<T>(new T(std::forward<Args>(args)...),
QObjectDeleteLaterDeletor<T>());
passes a const std::default_delete<T>&
to the constructor of std::unique_ptr<T>
, because that's what the constructor expects. Upon destruction (or call to member reset()
), this will be called.
Note that the behaviour of std::shared_ptr
is different: there is no second template argument for the deleter, though a custom deleter may be provided at construction (this will need to be stored via type erasure, which is avoided with std::unique_ptr
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.