- wip -
This commit is contained in:
Simon Brunel 2018-02-28 09:37:29 +01:00
parent 26a2110a14
commit 5523597e7c
6 changed files with 246 additions and 9 deletions

View File

@ -23,6 +23,9 @@ public:
template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count != 1, int>::type = 0> template <typename F, typename std::enable_if<QtPromisePrivate::ArgsOf<F>::count != 1, int>::type = 0>
inline QPromiseBase(F resolver); inline QPromiseBase(F resolver);
template <typename U>
inline QPromiseBase(const QPromise<U>& other);
QPromiseBase(const QPromiseBase<T>& other): m_d(other.m_d) {} QPromiseBase(const QPromiseBase<T>& other): m_d(other.m_d) {}
QPromiseBase(const QPromise<T>& other): m_d(other.m_d) {} QPromiseBase(const QPromise<T>& other): m_d(other.m_d) {}
QPromiseBase(QPromiseBase<T>&& other) Q_DECL_NOEXCEPT { swap(other); } QPromiseBase(QPromiseBase<T>&& other) Q_DECL_NOEXCEPT { swap(other); }
@ -94,6 +97,9 @@ public: // STATIC
inline static QPromise<T> resolve(const T& value); inline static QPromise<T> resolve(const T& value);
inline static QPromise<T> resolve(T&& value); inline static QPromise<T> resolve(T&& value);
template <typename U>
operator QPromise<U>();
private: private:
friend class QPromiseBase<T>; friend class QPromiseBase<T>;
}; };
@ -105,6 +111,9 @@ public:
template <typename F> template <typename F>
QPromise(F&& resolver): QPromiseBase<void>(std::forward<F>(resolver)) { } QPromise(F&& resolver): QPromiseBase<void>(std::forward<F>(resolver)) { }
template <typename T>
QPromise(const QPromise<T>& other);
public: // STATIC public: // STATIC
template <template <typename, typename...> class Sequence = QVector, typename ...Args> template <template <typename, typename...> class Sequence = QVector, typename ...Args>
inline static QPromise<void> all(const Sequence<QPromise<void>, Args...>& promises); inline static QPromise<void> all(const Sequence<QPromise<void>, Args...>& promises);

View File

@ -74,6 +74,19 @@ inline QPromiseBase<T>::QPromiseBase(F callback)
} }
} }
template <typename T>
template <typename U>
inline QPromiseBase<T>::QPromiseBase(const QPromise<U>& other)
: m_d(new QtPromisePrivate::PromiseData<T>())
{
using namespace QtPromisePrivate;
QPromiseResolve<T> resolve(*this);
QPromiseReject<T> reject(*this);
PromiseFulfill<QPromise<U> >::call(other, PromiseCast<U, T>::apply(resolve), reject);
}
template <typename T> template <typename T>
template <typename TFulfilled, typename TRejected> template <typename TFulfilled, typename TRejected>
inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise inline typename QtPromisePrivate::PromiseHandler<T, TFulfilled>::Promise
@ -244,6 +257,21 @@ inline QPromise<T> QPromise<T>::resolve(T&& value)
}); });
} }
template <typename T>
template <typename U>
QPromise<T>::operator QPromise<U>()
{
return QPromise<U>::resolve(U());
}
template <typename T>
QPromise<void>::QPromise(const QPromise<T>& other)
: QPromiseBase<void>([&](const QPromiseResolve<void>& resolve, const QPromiseReject<void>& reject) {
QtPromisePrivate::PromiseFulfill<QPromise<T> >::call(other, resolve, reject);
})
{
}
template <template <typename, typename...> class Sequence, typename ...Args> template <template <typename, typename...> class Sequence, typename ...Args>
inline QPromise<void> QPromise<void>::all(const Sequence<QPromise<void>, Args...>& promises) inline QPromise<void> QPromise<void>::all(const Sequence<QPromise<void>, Args...>& promises)
{ {

View File

@ -122,10 +122,8 @@ struct PromiseDeduce<QtPromise::QPromise<T>>
template <typename T> template <typename T>
struct PromiseFulfill struct PromiseFulfill
{ {
static void call( template <typename TResolve, typename TReject>
T&& value, static void call(T&& value, const TResolve& resolve, const TReject&)
const QtPromise::QPromiseResolve<T>& resolve,
const QtPromise::QPromiseReject<T>&)
{ {
resolve(std::move(value)); resolve(std::move(value));
} }
@ -134,10 +132,11 @@ struct PromiseFulfill
template <typename T> template <typename T>
struct PromiseFulfill<QtPromise::QPromise<T>> struct PromiseFulfill<QtPromise::QPromise<T>>
{ {
template <typename TResolve, typename TReject>
static void call( static void call(
const QtPromise::QPromise<T>& promise, const QtPromise::QPromise<T>& promise,
const QtPromise::QPromiseResolve<T>& resolve, const TResolve& resolve,
const QtPromise::QPromiseReject<T>& reject) const TReject& reject)
{ {
if (promise.isFulfilled()) { if (promise.isFulfilled()) {
resolve(promise.m_d->value()); resolve(promise.m_d->value());
@ -156,9 +155,9 @@ struct PromiseFulfill<QtPromise::QPromise<T>>
template <> template <>
struct PromiseFulfill<QtPromise::QPromise<void>> struct PromiseFulfill<QtPromise::QPromise<void>>
{ {
template <typename TPromise, typename TResolve, typename TReject> template <typename TResolve, typename TReject>
static void call( static void call(
const TPromise& promise, const QtPromise::QPromise<void>& promise,
const TResolve& resolve, const TResolve& resolve,
const TReject& reject) const TReject& reject)
{ {
@ -397,6 +396,67 @@ struct PromiseCatcher<T, std::nullptr_t, void>
} }
}; };
template <typename T, typename U>
struct PromiseCast
{
template <typename F>
static auto apply(const F& resolve)
{
return [=](const QSharedPointer<T>& value) {
resolve(static_cast<T>(*value));
};
}
};
template <typename T>
struct PromiseCast<T, void>
{
template <typename F>
static auto apply(const F& resolve)
{
return [=](const QSharedPointer<T>&) {
resolve();
};
}
};
/*
template <typename T>
struct PromiseCast<T, QVariant>
{
static QtPromise::QPromise<QVariant> cast(
const QtPromise::QPromiseBase<T>& input)
{
return input.then([](const T& res) {
return QVariant::fromValue(res);
});
}
};
template <typename U>
struct PromiseCast<QVariant, U>
{
static QtPromise::QPromise<U> cast(
const QtPromise::QPromiseBase<QVariant>& input)
{
return input.then([](const QVariant& res) {
return res.value<U>();
});
}
};
template <>
struct PromiseCast<void, QVariant>
{
static QtPromise::QPromise<void> cast(
const QtPromise::QPromiseBase<QVariant>& input)
{
return input.then([]() {
});
}
};
*/
template <typename T> class PromiseData; template <typename T> class PromiseData;
template <typename T, typename F> template <typename T, typename F>
@ -626,4 +686,4 @@ private:
} // namespace QtPromise } // namespace QtPromise
#endif // ifndef QTPROMISE_QPROMISE_H #endif // ifndef QTPROMISE_QPROMISE_P_H

View File

@ -0,0 +1,4 @@
TARGET = tst_qpromise_cast
SOURCES += $$PWD/tst_cast.cpp
include(../../qtpromise.pri)

View File

@ -0,0 +1,135 @@
// Tests
#include "../../shared/utils.h"
// QtPromise
#include <QtPromise>
// Qt
#include <QtTest>
using namespace QtPromise;
class tst_qpromise_cast : public QObject
{
Q_OBJECT
private Q_SLOTS:
void typeToVoid();
//void castToVoidOperator();
//void typeToVariant(); // QPromise<T>.cast<QVariant>()
//void variantToType();
//void voidToVariant(); // QPromise<void>.cast<QVariant>()
//void variantToVoid();
//void jsonValueToJsonObject();
};
QTEST_MAIN(tst_qpromise_cast)
#include "tst_cast.moc"
void tst_qpromise_cast::typeToVoid()
{
QPromise<void> p0 = QPromise<int>::resolve(42);
QPromise<void> p1 = QPromise<QString>::resolve(QString("foo"));
QVERIFY(p0.isFulfilled());
QVERIFY(p1.isFulfilled());
}
//void tst_qpromise_cast::castToVoidOperator()
//{
//auto p0 = QPromise<int>::resolve(42);
//QPromise<double> p1(p0);
//QPromise<void> p2(p0);
//auto p4 = QPromise<QString>::resolve("foo");
//
//p0.then([](int res) { qDebug() << res; });
//p1.then([](double res) { qDebug() << res; });
//p2.then([]() { qDebug() << "done"; });
//
//foo().then([]() {
// qDebug() << "done";
//}).wait();
//
//QPromise<QVariant>::all({p0, p1, p4}).then([](const QVector<QVariant>& res) {
// qDebug() << "all done!" << res;
//}).wait();
//}
/*
namespace {
template <typename T, typename U>
void test_qpromise_cast(const T& t, const U& u)
{
auto p = QPromise<T>::resolve(t).cast<U>();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<U> >::value));
QCOMPARE(waitForValue(p, U()), u);
}
template <typename U>
void test_qpromise_cast(const U& u)
{
auto p = QPromise<void>::resolve().cast<U>();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<U> >::value));
QCOMPARE(waitForValue(p, U()), u);
}
} // anonymous namespace
void tst_qpromise_cast::typeToVariant()
{
test_qpromise_cast(42, QVariant(42));
test_qpromise_cast(4.2, QVariant(4.2));
test_qpromise_cast(true, QVariant(true));
test_qpromise_cast(QString("foo"), QVariant(QString("foo")));
test_qpromise_cast(QUrl("http://x.y.z"), QVariant(QUrl("http://x.y.z")));
test_qpromise_cast(QSize(128, 256), QVariant(QSize(128, 256)));
test_qpromise_cast(QDate(2018, 1, 1), QVariant(QDate(2018, 1, 1)));
test_qpromise_cast(QJsonValue("foo"), QVariant(QJsonValue("foo")));
test_qpromise_cast(QStringList{"foo", "bar"}, QVariant(QStringList{"foo", "bar"}));
test_qpromise_cast(QList<QVariant>{"foo", 42}, QVariant(QList<QVariant>{"foo", 42}));
test_qpromise_cast(QMap<QString, QVariant>{{"foo", 42}}, QVariant(QVariantMap{{"foo", 42}}));
}
void tst_qpromise_cast::voidToVariant()
{
test_qpromise_cast(QVariant());
}
void tst_qpromise_cast::variantToType()
{
// invalid
// int
// QString
// QColor
// QList
}
/*
void tst_qpromise_cast::jsonValueToJsonObject()
{
{ // QJsonValue(Null) -> QJsonObject
auto p = QPromise<QJsonValue>::resolve(QJsonValue()).cast<QJsonObject>();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QJsonObject> >::value));
const QJsonObject res = waitForValue(p, QJsonObject());
QVERIFY(res.isEmpty());
}
{ // QJsonValue(int) -> QJsonObject
auto p = QPromise<QJsonValue>::resolve(QJsonValue(42)).cast<QJsonObject>();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QJsonObject> >::value));
const QJsonObject res = waitForValue(p, QJsonObject());
QVERIFY(res.isEmpty());
}
{ // QJsonValue(QJsonObject) -> QJsonObject
const QJsonObject object{{"magic", 42}};
auto p = QPromise<QJsonValue>::resolve(QJsonValue(object)).cast<QJsonObject>();
Q_STATIC_ASSERT((std::is_same<decltype(p), QPromise<QJsonObject> >::value));
const QJsonObject res = waitForValue(p, QJsonObject());
QCOMPARE(res.value("magic"), 42);
}
}
*/

View File

@ -1,6 +1,7 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS += \ SUBDIRS += \
all \ all \
cast \
construct \ construct \
delay \ delay \
fail \ fail \