Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Why Q_GADGET is not moved?



  • I have a C++ function that returns a gadget:

    class ZResult
    {
        Q_GADGET
        ...
    };
    
    Q_INVOKABLE ZResult findPeaks();
    

    When the function is called from QML

    var result = market.findPeaks()
    

    ZResult's copy constructor is called. Why is not it moved?

    see the call stack:

    MyApp.exe!ZResult::ZResult(const ZResult & other) Line 26	C++
    MyApp.exe!QtMetaTypePrivate::QMetaTypeFunctionHelper<ZResult,1>::Construct(void * where, const void * t) Line 825	C++
    Qt5Cored.dll!QMetaType::construct(void * where, const void * copy) Line 2367	C++
    Qt5Qmld.dll!QV4::Heap::QQmlValueTypeWrapper::setValue(const QVariant & value) Line 116	C++
    Qt5Qmld.dll!QV4::QQmlValueTypeWrapper::create(QV4::ExecutionEngine * engine, const QVariant & value, const QMetaObject * metaObject, int typeId) Line 220	C++
    Qt5Qmld.dll!QV4::ExecutionEngine::fromVariant(const QVariant & variant) Line 1781	C++
    Qt5Qmld.dll!`anonymous namespace'::CallArgument::toValue(QV4::ExecutionEngine * engine) Line 1974	C++
    Qt5Qmld.dll!CallMethod(const QQmlObjectOrGadget & object, int index, int returnType, int argCount, int * argTypes, QV4::ExecutionEngine * engine, QV4::CallData * callArgs, QMetaObject::Call callType) Line 1303	C++
    Qt5Qmld.dll!CallPrecise(const QQmlObjectOrGadget & object, const QQmlPropertyData & data, QV4::ExecutionEngine * engine, QV4::CallData * callArgs, QMetaObject::Call callType) Line 1566	C++
    Qt5Qmld.dll!QV4::QObjectMethod::callInternal(const QV4::Value * thisObject, const QV4::Value * argv, int argc) Line 2128	C++
    Qt5Qmld.dll!QV4::QObjectMethod::virtualCall(const QV4::FunctionObject * m, const QV4::Value * thisObject, const QV4::Value * argv, int argc) Line 2066	C++
    Qt5Qmld.dll!QV4::FunctionObject::call(const QV4::Value * thisObject, const QV4::Value * argv, int argc) Line 203	C++
    Qt5Qmld.dll!QV4::Moth::VME::interpret(QV4::CppStackFrame * frame, QV4::ExecutionEngine * engine, const char * code) Line 754	C++
    Qt5Qmld.dll!QV4::Moth::VME::exec(QV4::CppStackFrame * frame, QV4::ExecutionEngine * engine) Line 463	C++
    Qt5Qmld.dll!QV4::Function::call(const QV4::Value * thisObject, const QV4::Value * argv, int argc, const QV4::ExecutionContext * context) Line 69	C++
    Qt5Qmld.dll!QQmlJavaScriptExpression::evaluate(QV4::CallData * callData, bool * isUndefined) Line 212	C++
    Qt5Qmld.dll!QQmlBoundSignalExpression::evaluate(void * * a) Line 226	C++
    Qt5Qmld.dll!QQmlBoundSignal_callback(QQmlNotifierEndpoint * e, void * * a) Line 362	C++
    Qt5Qmld.dll!QQmlNotifier::emitNotify(QQmlNotifierEndpoint * endpoint, void * * a) Line 105	C++
    Qt5Qmld.dll!QQmlData::signalEmitted(QAbstractDeclarativeData * __formal, QObject * object, int index, void * * a) Line 836	C++
    Qt5Cored.dll!doActivate<0>(QObject * sender, int signal_index, void * * argv) Line 3782	C++
    Qt5Cored.dll!QMetaObject::activate(QObject * sender, const QMetaObject * m, int local_signal_index, void * * argv) Line 3947	C++
    Qt5QuickTemplates2d.dll!QQuickAbstractButton::clicked() Line 631	C++
    Qt5QuickTemplates2d.dll!QQuickAbstractButtonPrivate::trigger() Line 343	C++
    Qt5QuickTemplates2d.dll!QQuickAbstractButtonPrivate::handleRelease(const QPointF & point) Line 183	C++
    Qt5QuickTemplates2d.dll!QQuickControl::mouseReleaseEvent(QMouseEvent * event) Line 2150	C++
    Qt5Quickd.dll!QQuickItem::event(QEvent * ev) Line 8166	C++
    Qt5QuickTemplates2d.dll!QQuickAbstractButton::event(QEvent * event) Line 1034	C++
    Qt5Cored.dll!QCoreApplicationPrivate::notify_helper(QObject * receiver, QEvent * event) Line 1222	C++
    Qt5Cored.dll!doNotify(QObject * receiver, QEvent * event) Line 1151	C++
    Qt5Cored.dll!QCoreApplication::notify(QObject * receiver, QEvent * event) Line 1138	C++
    Qt5Guid.dll!QGuiApplication::notify(QObject * object, QEvent * event) Line 1880	C++
    Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1061	C++
    Qt5Cored.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event) Line 1457	C++
    Qt5Quickd.dll!QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent * pointerEvent) Line 1901	C++
    Qt5Quickd.dll!QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent * event) Line 2490	C++
    Qt5Quickd.dll!QQuickWindowPrivate::handleMouseEvent(QMouseEvent * event) Line 2308	C++
    Qt5Quickd.dll!QQuickWindow::mouseReleaseEvent(QMouseEvent * event) Line 2288	C++
    Qt5Guid.dll!QWindow::event(QEvent * ev) Line 2337	C++
    Qt5Quickd.dll!QQuickWindow::event(QEvent * e) Line 1783	C++
    Qt5Cored.dll!QCoreApplicationPrivate::notify_helper(QObject * receiver, QEvent * event) Line 1222	C++
    Qt5Cored.dll!doNotify(QObject * receiver, QEvent * event) Line 1151	C++
    Qt5Cored.dll!QCoreApplication::notify(QObject * receiver, QEvent * event) Line 1138	C++
    Qt5Guid.dll!QGuiApplication::notify(QObject * object, QEvent * event) Line 1880	C++
    Qt5Cored.dll!QCoreApplication::notifyInternal2(QObject * receiver, QEvent * event) Line 1061	C++
    Qt5Cored.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver, QEvent * event) Line 1469	C++
    Qt5Guid.dll!QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent * e) Line 2215	C++
    Qt5Guid.dll!QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e) Line 1947	C++
    Qt5Guid.dll!QWindowSystemInterface::sendWindowSystemEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 1181	C++
    qwindowsd.dll!QWindowsGuiEventDispatcher::sendPostedEvents() Line 82	C++
    Qt5Cored.dll!QEventDispatcherWin32::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 527	C++
    qwindowsd.dll!QWindowsGuiEventDispatcher::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 73	C++
    Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 140	C++
    Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags) Line 232	C++
    Qt5Cored.dll!QCoreApplication::exec() Line 1369	C++
    Qt5Guid.dll!QGuiApplication::exec() Line 1868	C++
    MyApp.exe!main(int argc, char * * argv) Line 112	C++
    MyApp.exe!invoke_main() Line 79	C++
    MyApp.exe!__scrt_common_main_seh() Line 288	C++
    MyApp.exe!__scrt_common_main() Line 331	C++
    MyApp.exe!mainCRTStartup() Line 17	C++

  • Lifetime Qt Champion

    Hi,

    Why should it be moved ?



  • @SGaist Probably it is not quite correct question. I would not say 'it should', but theoretically it can be moved because it is returned as a temporary value from my findPeaks() function.


  • Qt Champions 2017

    @Dmitriano said in Why Q_GADGET is not moved?:

    @SGaist Probably it is not quite correct question. I would not say 'it should', but theoretically it can be moved because it is returned as a temporary value from my findPeaks() function.

    This:

    var result = market.findPeaks()
    

    isn't c++, so copy elision (like the requested RVO) does not apply, nor is it applicable at all.



  • @kshegunov Sure, 'copy elision' is not applicable, but I asked about 'std::move' (note that it is not the same). Theoretically QT engine can determine that the only reference to the gadget exists in QML and call move constructor. At least it is not obvious why this is not possible.


  • Qt Champions 2017

    @Dmitriano said in Why Q_GADGET is not moved?:

    Sure, 'copy elision' is not applicable, but I asked about 'std::move' (note that it is not the same).

    Move semantics is there to facilitate copy elision, nothing else.

    Theoretically QT engine can determine that the only reference to the gadget exists in QML and call move constructor. At least it is not obvious why this is not possible.

    No it can't and yes, at least for me the reasoning is rather evident. C++ is a compiled language and is subject to static analysis and subsequent (asm) code generation + optimization. QML is neither of these things. How should or even could a dynamic language be "compiled in" asm, when the latter is already compiled into a target binary? (and that's of course assuming that the whole set of tools for such a thing are available in-language, which they aren't)
    Basically you're asking "why isn't c++ code recompiling itself while running".


Log in to reply