1

I'd like to run simple method in a different thread than the GUI thread inside my Qt application. To do this I'm using QFuture and Qt Concurrent. However, I ran into a compile error:

C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent/qtconcurrentstoredfunctioncall.h(58): error C2280: 'QtConcurrent::RunFunctionTask<T>::RunFunctionTask(void)': attempting to reference a deleted function
        with
        [
            T=Error
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent/qtconcurrentrunbase.h(121): note: compiler has generated 'QtConcurrent::RunFunctionTask<T>::RunFunctionTask' here
        with
        [
            T=Error
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent/qtconcurrentrunbase.h(121): note: 'QtConcurrent::RunFunctionTask<T>::RunFunctionTask(void)': function was implicitly deleted because a data member 'QtConcurrent::RunFunctionTask<T>::result' has either no appropriate default constructor or overload resolution was ambiguous
        with
        [
            T=Error
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent/qtconcurrentrunbase.h(120): note: see declaration of 'QtConcurrent::RunFunctionTask<T>::result'
        with
        [
            T=Error
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent/qtconcurrentstoredfunctioncall.h(58): note: while compiling class template member function 'QtConcurrent::StoredFunctorCall0<T,T (__cdecl *)(void)>::StoredFunctorCall0(FunctionPointer)'
        with
        [
            T=Error,
            FunctionPointer=Error (__cdecl *)(void)
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent\qtconcurrentrun.h(74): note: see reference to function template instantiation 'QtConcurrent::StoredFunctorCall0<T,T (__cdecl *)(void)>::StoredFunctorCall0(FunctionPointer)' being compiled
        with
        [
            T=Error,
            FunctionPointer=Error (__cdecl *)(void)
        ]
C:\Qt\5.15.2\msvc2019_64\include\QtConcurrent\qtconcurrentrun.h(74): note: see reference to class template instantiation 'QtConcurrent::StoredFunctorCall0<T,T (__cdecl *)(void)>' being compiled
        with
        [
            T=Error
        ]
C:\Users\dalji\Documents\Dev\TestQtConcurrent\main.cpp(37): note: see reference to function template instantiation 'QFuture<Error> QtConcurrent::run<Error>(T (__cdecl *)(void))' being compiled
        with
        [
            T=Error
        ]
ninja: build stopped: subcommand failed.
16:14:59: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 1.
Error while building/deploying project TestQtConcurrent (kit: Desktop Qt 5.15.2 MSVC2019 64bit)
When executing step "Build"

Here is a simple test application that reproduces the issue I'm having

#include <QCoreApplication>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>

class Error
{
public:
    enum class ErrorType {
        NoError,
        FileSavingError,
        FileLoadingError
    };
    Error(ErrorType errorType, const QString &errorMessage  = "") :
        m_errorType(errorType),
        m_errorMessage(errorMessage)
    {

    }
    const QString &errorMessage() const { return m_errorMessage; }
    ErrorType errorType() const {  return m_errorType; }

private:
    ErrorType m_errorType;
    QString m_errorMessage;
};


Error testMethod(){
    return Error(Error::ErrorType::NoError, "No Error");
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QFuture<Error> errorFuture = QtConcurrent::run(testMethod);
    return a.exec();
}

What am I doing wrong?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
mathripper
  • 299
  • 1
  • 12
  • Error messages often comes with informational notes. Please copy-paste the *full* and *complete* build output into your question. – Some programmer dude Feb 21 '22 at 16:14
  • You are missing a default constructor for `Error`. Add e.g. `Error() : m_errorType(ErrorType::NoError) {}` – Adriaan de Groot Feb 21 '22 at 16:21
  • 1
    Why is a default constructor needed? – mathripper Feb 21 '22 at 16:22
  • While you should always include the complete build output when you ask about build errors, in this case MSVC is less than helpful and doesn't really state out loud that a default constructor is needed. Other compilers (like e.g. GCC) give more long-winded error messages but at least state that a default constructor is needed. – Some programmer dude Feb 21 '22 at 16:24
  • Nothing in the docs says it must have one, this was just the quickest way I could come up with to get it to compile at all (hence, not an answer). – Adriaan de Groot Feb 21 '22 at 16:24
  • 2
    Read `QFuture` reference, *The result can be of any type that has a default constructor and a copy constructor.* [ref](https://doc.qt.io/qt-5/qfuture.html) – rafix07 Feb 21 '22 at 16:25

1 Answers1

1

As noted in the comments, and as indicated in the error message itself, the problem is that your Error class has no default constructor.

While there is nothing explicit in the documentation for QtConcurrentRun that indicates this requirement, there is the following in the documentation for QFuture (bold emphasis mine)1:

QFuture allows threads to be synchronized against one or more results which will be ready at a later point in time. The result can be of any type that has a default constructor and a copy constructor. …

The simplest way to add the required default constructor to your Error class is to add a default value for the first argument (you already have one for the second argument) in your currently-defined constructor (I've assumed that the ErrorType::NoError enumeration is a sensible value for this default):

    Error(ErrorType errorType = ErrorType::NoError, const QString& errorMessage = "") :
        m_errorType(errorType),
        m_errorMessage(errorMessage)
    {
    }

1 Note that, for your Error class, the (also required) copy constructor is implicitly declared and will be generated for you, by the compiler.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83