Fix MSVC 2013 compilation issues

This commit is contained in:
Simon Brunel 2017-09-04 00:20:53 +02:00
parent 0682269d8f
commit 931d5d5b13
8 changed files with 72 additions and 18 deletions

7
.gitignore vendored
View File

@ -2,6 +2,11 @@
*.gcda *.gcda
*.moc *.moc
*.o *.o
*.obj
*.exe
*.user *.user
Makefile Makefile*
moc_*.cpp
moc_*.h
coverage.info coverage.info
target_wrapper.bat

View File

@ -32,9 +32,13 @@ public:
bool isRejected() const { return m_d->isRejected(); } bool isRejected() const { return m_d->isRejected(); }
bool isPending() const { return m_d->isPending(); } bool isPending() const { return m_d->isPending(); }
template <typename TFulfilled, typename TRejected = std::nullptr_t> template <typename TFulfilled, typename TRejected>
inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise
then(const TFulfilled& fulfilled, const TRejected& rejected = nullptr) const; then(const TFulfilled& fulfilled, const TRejected& rejected) const;
template <typename TFulfilled>
inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise
then(TFulfilled&& fulfilled) const;
template <typename TRejected> template <typename TRejected>
inline typename QtPromisePrivate::PromiseHandler<T, std::nullptr_t>::Promise inline typename QtPromisePrivate::PromiseHandler<T, std::nullptr_t>::Promise
@ -67,7 +71,7 @@ protected:
}; };
template <typename T> template <typename T>
class QPromise: public QPromiseBase<T> class QPromise : public QPromiseBase<T>
{ {
public: public:
template <typename F> template <typename F>
@ -82,7 +86,7 @@ private:
}; };
template <> template <>
class QPromise<void>: public QPromiseBase<void> class QPromise<void> : public QPromiseBase<void>
{ {
public: public:
template <typename F> template <typename F>

View File

@ -122,6 +122,14 @@ QPromiseBase<T>::then(const TFulfilled& fulfilled, const TRejected& rejected) co
return next; return next;
} }
template <typename T>
template <typename TFulfilled>
inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise
QPromiseBase<T>::then(TFulfilled&& fulfilled) const
{
return then(std::forward<TFulfilled>(fulfilled), nullptr);
}
template <typename T> template <typename T>
template <typename TRejected> template <typename TRejected>
inline typename QtPromisePrivate::PromiseHandler<T, std::nullptr_t>::Promise inline typename QtPromisePrivate::PromiseHandler<T, std::nullptr_t>::Promise

View File

@ -508,7 +508,7 @@ private:
template <> template <>
class PromiseData<void> : public PromiseDataBase<void, void()> class PromiseData<void> : public PromiseDataBase<void, void()>
{ {
using Handler = typename PromiseDataBase<void, void()>::Handler; using Handler = PromiseDataBase<void, void()>::Handler;
public: public:
void resolve() void resolve()

View File

@ -16,18 +16,18 @@ using Unqualified = typename std::remove_cv<typename std::remove_reference<T>::t
/*! /*!
* \struct HasCallOperator * \struct HasCallOperator
* http://stackoverflow.com/a/5839442 * http://stackoverflow.com/a/5117641
*/ */
template <typename T> template <typename T>
struct HasCallOperator struct HasCallOperator
{ {
template <class U> template <typename U>
static auto check(const U* u) static char check(decltype(&U::operator(), char(0)));
-> decltype(&U::operator(), char(0));
static std::array<char, 2> check(...); template <typename U>
static char (&check(...))[2];
static const bool value = (sizeof(check((T*)0)) == 1); static const bool value = (sizeof(check<T>(0)) == 1);
}; };
/*! /*!

View File

@ -4,6 +4,14 @@
// Qt // Qt
#include <QtTest> #include <QtTest>
#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; using namespace QtPromise;
class tst_benchmark : public QObject class tst_benchmark : public QObject
@ -58,6 +66,35 @@ struct Data : public Logger
Data(int v): Logger(), m_value(v) {} Data(int v): Logger(), m_value(v) {}
int value() const { return m_value; } 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<Data>(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<Data>(other));
qSwap(m_value, other.m_value);
return *this;
}
private: private:
int m_value; int m_value;
}; };
@ -264,7 +301,7 @@ void tst_benchmark::errorReject()
}).wait(); }).wait();
QCOMPARE(Data::logs().ctor, 1); 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().move, 0);
QCOMPARE(Data::logs().refs, 0); QCOMPARE(Data::logs().refs, 0);
} }
@ -276,7 +313,7 @@ void tst_benchmark::errorReject()
}).wait(); }).wait();
QCOMPARE(Data::logs().ctor, 1); 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().move, 0);
QCOMPARE(Data::logs().refs, 0); QCOMPARE(Data::logs().refs, 0);
} }
@ -292,7 +329,7 @@ void tst_benchmark::errorThen()
}).wait(); }).wait();
QCOMPARE(Data::logs().ctor, 1); 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().move, 0);
QCOMPARE(Data::logs().refs, 0); QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42); QCOMPARE(value, 42);
@ -307,7 +344,7 @@ void tst_benchmark::errorThen()
}).wait(); }).wait();
QCOMPARE(Data::logs().ctor, 1); 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().move, 0);
QCOMPARE(Data::logs().refs, 0); QCOMPARE(Data::logs().refs, 0);
QCOMPARE(value, 42); QCOMPARE(value, 42);

View File

@ -262,7 +262,7 @@ void tst_future::fail()
auto input = QPromise<QString>::reject(MyException("bar")); auto input = QPromise<QString>::reject(MyException("bar"));
auto output = input.fail([](const MyException& e) { auto output = input.fail([](const MyException& e) {
return QtConcurrent::run([=]() { return QtConcurrent::run([=]() {
return QString("foo") + e.error(); return QString("foo%1").arg(e.error());
}); });
}); });

View File

@ -216,7 +216,7 @@ void tst_requirements::thenOnFulfilled()
// with promises value as its first argument. // with promises value as its first argument.
QVERIFY(p0.isFulfilled()); QVERIFY(p0.isFulfilled());
QVERIFY(p1.isFulfilled()); QVERIFY(p1.isFulfilled());
QCOMPARE(values, QVector<int>({42})); QCOMPARE(values, QVector<int>{42});
} }
void tst_requirements::thenOnRejected() void tst_requirements::thenOnRejected()