diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 1ec626a53b..e3ba1e4449 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -925,6 +925,30 @@ bool QThread::isInterruptionRequested() const \sa start() */ +#ifdef QTHREAD_HAS_CREATE +class QThreadCreateThread : public QThread +{ +public: + explicit QThreadCreateThread(std::future &&future) + : m_future(std::move(future)) + { + } + +private: + void run() override + { + m_future.get(); + } + + std::future m_future; +}; + +QThread *QThread::createThreadImpl(std::future &&future) +{ + return new QThreadCreateThread(std::move(future)); +} +#endif // QTHREAD_HAS_CREATE + /*! \class QDaemonThread \since 5.5 diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 8f87888162..670197d375 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -165,98 +165,81 @@ protected: private: Q_DECLARE_PRIVATE(QThread) +#ifdef QTHREAD_HAS_CREATE + static QThread *createThreadImpl(std::future &&future); +#endif + friend class QCoreApplication; friend class QThreadData; }; #ifdef QTHREAD_HAS_CREATE -namespace QtPrivate { - -class QThreadCreateThread : public QThread -{ -public: -#if defined(QTHREAD_HAS_VARIADIC_CREATE) - // C++17: std::thread's constructor complying call - template - explicit QThreadCreateThread(Function &&f, Args &&... args) - : m_future(std::async(std::launch::deferred, - [f = static_cast::type>(std::forward(f))](auto &&... largs) mutable -> void - { - (void)std::invoke(std::move(f), std::forward(largs)...); - }, std::forward(args)...)) - { - } -#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304 - // C++14: implementation for just one callable - template - explicit QThreadCreateThread(Function &&f) - : m_future(std::async(std::launch::deferred, - [f = static_cast::type>(std::forward(f))]() mutable -> void - { - (void)f(); - })) - { - } -#else -private: - // C++11: same as C++14, but with a workaround for not having generalized lambda captures - template - struct Callable - { - explicit Callable(Function &&f) - : m_function(std::forward(f)) - { - } - -#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) - // Apply the same semantics of a lambda closure type w.r.t. the special - // member functions, if possible: delete the copy assignment operator, - // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure]) - ~Callable() = default; - Callable(const Callable &) = default; - Callable(Callable &&) = default; - Callable &operator=(const Callable &) = delete; - Callable &operator=(Callable &&) = default; -#endif - - void operator()() - { - (void)m_function(); - } - - typename std::decay::type m_function; - }; - -public: - template - explicit QThreadCreateThread(Function &&f) - : m_future(std::async(std::launch::deferred, Callable(std::forward(f)))) - { - } -#endif // QTHREAD_HAS_VARIADIC_CREATE - -private: - void run() override - { - m_future.get(); - } - - std::future m_future; -}; - -} // namespace QtPrivate #ifdef QTHREAD_HAS_VARIADIC_CREATE +// C++17: std::thread's constructor complying call template QThread *QThread::create(Function &&f, Args &&... args) { - return new QtPrivate::QThreadCreateThread(std::forward(f), std::forward(args)...); + using DecayedFunction = typename std::decay::type; + auto threadFunction = + [f = static_cast(std::forward(f))](auto &&... largs) mutable -> void + { + (void)std::invoke(std::move(f), std::forward(largs)...); + }; + + return createThreadImpl(std::async(std::launch::deferred, + std::move(threadFunction), + std::forward(args)...)); } -#else +#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304 +// C++14: implementation for just one callable template QThread *QThread::create(Function &&f) { - return new QtPrivate::QThreadCreateThread(std::forward(f)); + using DecayedFunction = typename std::decay::type; + auto threadFunction = + [f = static_cast(std::forward(f))]() mutable -> void + { + (void)f(); + }; + + return createThreadImpl(std::async(std::launch::deferred, std::move(threadFunction))); +} +#else +// C++11: same as C++14, but with a workaround for not having generalized lambda captures +namespace QtPrivate { +template +struct Callable +{ + explicit Callable(Function &&f) + : m_function(std::forward(f)) + { + } + +#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) + // Apply the same semantics of a lambda closure type w.r.t. the special + // member functions, if possible: delete the copy assignment operator, + // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure]) + ~Callable() = default; + Callable(const Callable &) = default; + Callable(Callable &&) = default; + Callable &operator=(const Callable &) = delete; + Callable &operator=(Callable &&) = default; +#endif + + void operator()() + { + (void)m_function(); + } + + typename std::decay::type m_function; +}; +} // namespace QtPrivate + +template +QThread *QThread::create(Function &&f) +{ + return createThreadImpl(std::async(std::launch::deferred, QtPrivate::Callable(std::forward(f)))); } #endif // QTHREAD_HAS_VARIADIC_CREATE