From 931d5d5b135ad9192028b0b3d2d3df75360adb76 Mon Sep 17 00:00:00 2001 From: Simon Brunel Date: Mon, 4 Sep 2017 00:20:53 +0200 Subject: [PATCH] Fix MSVC 2013 compilation issues --- .gitignore | 7 ++- src/qtpromise/qpromise.h | 12 ++++-- src/qtpromise/qpromise.inl | 8 ++++ src/qtpromise/qpromise_p.h | 2 +- src/qtpromise/qpromiseglobal.h | 12 +++--- tests/auto/benchmark/tst_benchmark.cpp | 45 ++++++++++++++++++-- tests/auto/future/tst_future.cpp | 2 +- tests/auto/requirements/tst_requirements.cpp | 2 +- 8 files changed, 72 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index bbeffbd..dd3d84a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,11 @@ *.gcda *.moc *.o +*.obj +*.exe *.user -Makefile +Makefile* +moc_*.cpp +moc_*.h coverage.info +target_wrapper.bat diff --git a/src/qtpromise/qpromise.h b/src/qtpromise/qpromise.h index e80862a..8504ca0 100644 --- a/src/qtpromise/qpromise.h +++ b/src/qtpromise/qpromise.h @@ -32,9 +32,13 @@ public: bool isRejected() const { return m_d->isRejected(); } bool isPending() const { return m_d->isPending(); } - template + template inline typename QtPromisePrivate::PromiseHandler::Promise - then(const TFulfilled& fulfilled, const TRejected& rejected = nullptr) const; + then(const TFulfilled& fulfilled, const TRejected& rejected) const; + + template + inline typename QtPromisePrivate::PromiseHandler::Promise + then(TFulfilled&& fulfilled) const; template inline typename QtPromisePrivate::PromiseHandler::Promise @@ -67,7 +71,7 @@ protected: }; template -class QPromise: public QPromiseBase +class QPromise : public QPromiseBase { public: template @@ -82,7 +86,7 @@ private: }; template <> -class QPromise: public QPromiseBase +class QPromise : public QPromiseBase { public: template diff --git a/src/qtpromise/qpromise.inl b/src/qtpromise/qpromise.inl index e3bd45c..def9017 100644 --- a/src/qtpromise/qpromise.inl +++ b/src/qtpromise/qpromise.inl @@ -122,6 +122,14 @@ QPromiseBase::then(const TFulfilled& fulfilled, const TRejected& rejected) co return next; } +template +template +inline typename QtPromisePrivate::PromiseHandler::Promise +QPromiseBase::then(TFulfilled&& fulfilled) const +{ + return then(std::forward(fulfilled), nullptr); +} + template template inline typename QtPromisePrivate::PromiseHandler::Promise diff --git a/src/qtpromise/qpromise_p.h b/src/qtpromise/qpromise_p.h index 439d50c..f2012a5 100644 --- a/src/qtpromise/qpromise_p.h +++ b/src/qtpromise/qpromise_p.h @@ -508,7 +508,7 @@ private: template <> class PromiseData : public PromiseDataBase { - using Handler = typename PromiseDataBase::Handler; + using Handler = PromiseDataBase::Handler; public: void resolve() diff --git a/src/qtpromise/qpromiseglobal.h b/src/qtpromise/qpromiseglobal.h index 92b543e..a868e91 100644 --- a/src/qtpromise/qpromiseglobal.h +++ b/src/qtpromise/qpromiseglobal.h @@ -16,18 +16,18 @@ using Unqualified = typename std::remove_cv::t /*! * \struct HasCallOperator - * http://stackoverflow.com/a/5839442 + * http://stackoverflow.com/a/5117641 */ template struct HasCallOperator { - template - static auto check(const U* u) - -> decltype(&U::operator(), char(0)); + template + static char check(decltype(&U::operator(), char(0))); - static std::array check(...); + template + static char (&check(...))[2]; - static const bool value = (sizeof(check((T*)0)) == 1); + static const bool value = (sizeof(check(0)) == 1); }; /*! diff --git a/tests/auto/benchmark/tst_benchmark.cpp b/tests/auto/benchmark/tst_benchmark.cpp index 0653a23..a121cc4 100644 --- a/tests/auto/benchmark/tst_benchmark.cpp +++ b/tests/auto/benchmark/tst_benchmark.cpp @@ -4,6 +4,14 @@ // Qt #include +#ifdef Q_CC_MSVC + // MSVC calls the copy constructor on std::current_exception AND std::rethrow_exception + // https://stackoverflow.com/a/31820854 + #define EXCEPT_CALL_COPY_CTOR 1 +#else + #define EXCEPT_CALL_COPY_CTOR 0 +#endif + using namespace QtPromise; class tst_benchmark : public QObject @@ -58,6 +66,35 @@ struct Data : public Logger Data(int v): Logger(), m_value(v) {} int value() const { return m_value; } + // MSVC 2013 doesn't support implicit generation of the move constructor and + // operator, so we need to explicitly define these methods and thus the copy + // constructor and operator also need to be explicitly defined (error C2280). + // https://stackoverflow.com/a/26581337 + + Data(const Data& other) + : Logger(other) + , m_value(other.m_value) + { } + + Data(Data&& other) : Logger(std::forward(other)) + { + qSwap(m_value, other.m_value); + } + + Data& operator=(const Data& other) + { + Logger::operator=(other); + m_value = other.m_value; + return *this; + } + + Data& operator=(Data&& other) + { + Logger::operator=(std::forward(other)); + qSwap(m_value, other.m_value); + return *this; + } + private: int m_value; }; @@ -264,7 +301,7 @@ void tst_benchmark::errorReject() }).wait(); QCOMPARE(Data::logs().ctor, 1); - QCOMPARE(Data::logs().copy, 1); // copy value in std::exception_ptr + QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value in std::exception_ptr QCOMPARE(Data::logs().move, 0); QCOMPARE(Data::logs().refs, 0); } @@ -276,7 +313,7 @@ void tst_benchmark::errorReject() }).wait(); QCOMPARE(Data::logs().ctor, 1); - QCOMPARE(Data::logs().copy, 1); // copy value to the promise data + QCOMPARE(Data::logs().copy, 1 + EXCEPT_CALL_COPY_CTOR); // copy value to the promise data QCOMPARE(Data::logs().move, 0); QCOMPARE(Data::logs().refs, 0); } @@ -292,7 +329,7 @@ void tst_benchmark::errorThen() }).wait(); QCOMPARE(Data::logs().ctor, 1); - QCOMPARE(Data::logs().copy, 1); // (initial) copy value in std::exception_ptr + QCOMPARE(Data::logs().copy, 1 + 2 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr QCOMPARE(Data::logs().move, 0); QCOMPARE(Data::logs().refs, 0); QCOMPARE(value, 42); @@ -307,7 +344,7 @@ void tst_benchmark::errorThen() }).wait(); QCOMPARE(Data::logs().ctor, 1); - QCOMPARE(Data::logs().copy, 1); // (initial) copy value in std::exception_ptr + QCOMPARE(Data::logs().copy, 1 + 4 * EXCEPT_CALL_COPY_CTOR); // (initial) copy value in std::exception_ptr QCOMPARE(Data::logs().move, 0); QCOMPARE(Data::logs().refs, 0); QCOMPARE(value, 42); diff --git a/tests/auto/future/tst_future.cpp b/tests/auto/future/tst_future.cpp index a090f2d..072d287 100644 --- a/tests/auto/future/tst_future.cpp +++ b/tests/auto/future/tst_future.cpp @@ -262,7 +262,7 @@ void tst_future::fail() auto input = QPromise::reject(MyException("bar")); auto output = input.fail([](const MyException& e) { return QtConcurrent::run([=]() { - return QString("foo") + e.error(); + return QString("foo%1").arg(e.error()); }); }); diff --git a/tests/auto/requirements/tst_requirements.cpp b/tests/auto/requirements/tst_requirements.cpp index efbc519..5253865 100644 --- a/tests/auto/requirements/tst_requirements.cpp +++ b/tests/auto/requirements/tst_requirements.cpp @@ -216,7 +216,7 @@ void tst_requirements::thenOnFulfilled() // with promise’s value as its first argument. QVERIFY(p0.isFulfilled()); QVERIFY(p1.isFulfilled()); - QCOMPARE(values, QVector({42})); + QCOMPARE(values, QVector{42}); } void tst_requirements::thenOnRejected()