C2665: 'QObject::connect' : none of the 3

2019-07-10 13:18发布

问题:

I have the following code in main

         QProcess process;
        QObject::connect(&process, &QProcess::error, [](QProcess::ProcessError error)
        {
            qDebug() << error;
        }, Qt::QueuedConnection);
        bool launched = process.startDetached("D:\temp.exe");

and it is generating this error while compiling

    D:\main.cpp:5: error: C2665: 'QObject::connect' : none of the 3 overloads could convert all the argument types c:\qt\5.3\msvc2013_64\include\qtcore\qobject.h(205): could be 
'QMetaObject::Connection QObject::connect(const QObject *,const char
    *,const char *,Qt::ConnectionType) const' c:\qt\5.3\msvc2013_64\include\qtcore\qobject.h(201): or 
      'QMetaObject::Connection QObject::connect(const QObject *,const QMetaMethod &,const QObject *,const QMetaMethod &,Qt::ConnectionType)' c:\qt\5.3\msvc2013_64\include\qtcore\qobject.h(198): or      
 'QMetaObject::Connection QObject::connect(const QObject *,const char
    *,const QObject *,const char *,Qt::ConnectionType)' while trying to match the argument list '(QProcess *, overloaded-function, RunGUIMode::<lambda_5d6e7ee926a623cea2a0e4469253d55f>, Qt::ConnectionType)'

can someone please help me out and tell me what i am doing wrong.

I want to connect a signal from the QProcess class to my lambda

回答1:

I shouldn't post this answer, but to be honest it is not same question, it is more complex.

First of all, why first version doesn't work. Because you can't use additional argument (connection type) without providing receiver. It means that next is wrong.

connect(&process, static_cast<void (QProcess::*)(QProcess::ProcessError)>
        (&QProcess::error),[=](QProcess::ProcessError pError) {
        qWarning() << "error " << pError;
},Qt::QueuedConnection);

But next is correct:

connect(&process, static_cast<void (QProcess::*)(QProcess::ProcessError)>
        (&QProcess::error), this , [=](QProcess::ProcessError pError) {
        qWarning() << "error " << pError;
},Qt::QueuedConnection);

If you wonder why, look at the qobject.h. I make some changes in this file, just to be more accurate (don't change this file!).

//first
//connect to a functor
template <typename Func1, typename Func2>
static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
{
    qDebug("There is no here argument for connection, isn't it?");
    return connect(sender, signal, sender, slot, Qt::DirectConnection);
}

//second
//connect to a functor, with a "context" object defining in which event loop is going to be executed
template <typename Func1, typename Func2>
static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
        Qt::ConnectionType type = Qt::AutoConnection)
{
    qDebug("This will be called, and as you can see you need specify the context if you want to use connection type.");
    //...

Secondly when you run this code, you will get:

QObject::connect: Cannot queue arguments of type 'QProcess::ProcessError' (Make sure 'QProcess::ProcessError' is registered using qRegisterMetaType().)

So you need add qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError"); before the connection.

So final version is:

qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
QProcess process;
connect(&process, static_cast<void (QProcess::*)(QProcess::ProcessError)>
        (&QProcess::error), this , [=](QProcess::ProcessError pError) {
    qWarning() << "error " << pError;
},Qt::QueuedConnection);
process.start("MyProgram");
bool launched = process.startDetached("example");