Rui Sebastião
Rui Sebastião

Reputation: 883

specialized std::default_delete with QQmlComponent

I'm trying to 'specialize' the std::default_delete for QQmlComponent without success,my implementation is never called, only the default deleter from ::std is called. So for debugging purposes i create another specialization for QObject and this one is called:

in my util.h i have:

namespace std {
    // QQmlComponent often theses objects
    // are owned by another thread despite their QQmlEngine::CppOwnership, using delete operator
    // directly generate crashes, specify a default_delete specifically for QQmlComponent to
    // use a deleteLater() call over a raw delete

    template<>
    struct  default_delete<QQmlComponent> {
        void operator()(QQmlComponent* ptr) {
            if ( ptr &&
                 QQmlEngine::objectOwnership(ptr) == QQmlEngine::CppOwnership )
                ptr->deleteLater();
        }
    };


    template<>
    struct  default_delete<QObject> {
        void operator()(QObject* ptr) {
           ///...
    };


   }

in my utils.cpp i have:

std::unique_ptr<QObject> testQObject= std::make_unique<QObject>(new QObject());

std::unique_ptr<QQmlComponent> connectorComponent = std::make_unique<QQmlComponent>(engine, QStringLiteral("qrc:/QuickQanava/VisualConnector.qml"));

in testQObject the specialized default_delete is called and not in connectorComponent

I don't understand what i'm doing wrong. As side note, this code is implemented in a shared library

Upvotes: 0

Views: 204

Answers (1)

catnip
catnip

Reputation: 25388

I don't know why your default_delete specialisation isn't being called but I can offer you an alternative - you can supply a custom deleter to std::unique_ptr instead and solve your problem that way.

You do it like this (you don't have to use a lambda if you can't or don't want to):

using SmartComponentPtr = std::unique_ptr <QQmlComponent, void (*) (QQmlComponent *)>;

inline SmartComponentPtr MakeSmartComponentPtr (QQmlComponent *component)
{
    return SmartComponentPtr (component, [] (auto component) { /* do funky stuff to delete component here */ } );
};

QQmlComponent *MyComponentPointer = ...
SmartComponentPtr smart_component_pointer = MakeSmartComponentPtr (MyComponentPointer);
// ...

A shared_ptr can also have a custom deleter, although this costs more.

I created a simple live demo at Wandbox, which also includes the non-lambda version as comments.

Upvotes: 1

Related Questions