diff options
| author | Linus Jahn <lnj@kaidan.im> | 2021-07-05 16:59:09 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2021-07-05 18:07:28 +0200 |
| commit | af3f0c1f5b36757867bf719dc27786e9f947024c (patch) | |
| tree | abfefdd6e7b1f9173fc9a7f36d822d044c45e46a /src/base | |
| parent | f79990e13fffd36a5d2aa4153ef06b48c0eeebe4 (diff) | |
| download | qxmpp-af3f0c1f5b36757867bf719dc27786e9f947024c.tar.gz | |
More template magic for QFutures
Diffstat (limited to 'src/base')
| -rw-r--r-- | src/base/QXmppFutureUtils_p.h | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/src/base/QXmppFutureUtils_p.h b/src/base/QXmppFutureUtils_p.h index d109f74b..9d188241 100644 --- a/src/base/QXmppFutureUtils_p.h +++ b/src/base/QXmppFutureUtils_p.h @@ -53,17 +53,31 @@ struct overloaded : Ts... { template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; +template<typename F, typename Ret, typename A, typename... Rest> +A lambda_helper(Ret (F::*)(A, Rest...)); + +template<typename F, typename Ret, typename A, typename... Rest> +A lambda_helper(Ret (F::*)(A, Rest...) const); + +template<typename F> +struct first_argument { + using type = decltype(lambda_helper(&F::operator())); +}; + +template<typename F> +using first_argument_t = typename first_argument<F>::type; + template<typename T> QFuture<T> makeReadyFuture(T &&value) { QFutureInterface<T> interface(QFutureInterfaceBase::Started); - interface.reportResult(value); + interface.reportResult(std::move(value)); interface.reportFinished(); return interface.future(); } template<typename Result, typename Input, typename Converter> -QFuture<Result> chain(QFuture<Input> &&source, QObject *context, Converter task) +auto chain(QFuture<Input> &&source, QObject *context, Converter task) -> QFuture<Result> { auto resultInterface = std::make_shared<QFutureInterface<Result>>(QFutureInterfaceBase::Started); @@ -77,9 +91,10 @@ QFuture<Result> chain(QFuture<Input> &&source, QObject *context, Converter task) return resultInterface->future(); } -template<typename Result, typename IqType, typename Input, typename Converter> -Result parseIq(Input &&sendResult, Converter convert) +template<typename IqType, typename Input, typename Converter> +auto parseIq(Input &&sendResult, Converter convert) -> decltype(convert({})) { + using Result = decltype(convert({})); return std::visit(overloaded { [convert { std::move(convert) }](const QDomElement &element) -> Result { IqType iq; @@ -98,28 +113,32 @@ Result parseIq(Input &&sendResult, Converter convert) sendResult); } -template<typename Result, typename IqType, typename Input> -Result parseIq(Input &&sendResult) +template<typename IqType, typename Result, typename Input> +auto parseIq(Input &&sendResult) -> Result { - return parseIq<Result, IqType>(std::move(sendResult), [](IqType &&iq) { + return parseIq<IqType>(std::move(sendResult), [](IqType &&iq) -> Result { // no conversion return iq; }); } -template<typename Result, typename IqType, typename Input, typename Converter> -QFuture<Result> chainIq(QFuture<Input> &&input, QObject *context, Converter convert) +template<typename Input, typename Converter> +auto chainIq(QFuture<Input> &&input, QObject *context, Converter convert) -> QFuture<decltype(convert({}))> { + using Result = decltype(convert({})); + using IqType = std::decay_t<first_argument_t<Converter>>; return chain<Result>(std::move(input), context, [convert { std::move(convert) }](Input &&input) -> Result { - return parseIq<Result, IqType>(std::move(input), convert); + return parseIq<IqType>(std::move(input), convert); }); } -template<typename Result, typename IqType, typename Input> -QFuture<Result> chainIq(QFuture<Input> &&input, QObject *context) +template<typename Result, typename Input> +auto chainIq(QFuture<Input> &&input, QObject *context) -> QFuture<Result> { + // IQ type is first std::variant parameter + using IqType = std::decay_t<decltype(std::get<0>(Result {}))>; return chain<Result>(std::move(input), context, [](Input &&sendResult) { - return parseIq<Result, IqType>(sendResult); + return parseIq<IqType, Result>(sendResult); }); } |
