libquentier  0.8.0
The library for rich desktop clients of Evernote service
QtFutureHelpers.h
1 /*
2  * Copyright 2021-2024 Dmitry Ivanov
3  *
4  * This file is part of libquentier
5  *
6  * libquentier is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, version 3 of the License.
9  *
10  * libquentier is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libquentier. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include <QFuture>
22 
23 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
24 #include "Qt5Promise.h"
25 #endif
26 
27 #include <type_traits>
28 
29 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
30 // Backports of some helpers for QFuture continuations from Qt6 to Qt5
31 namespace QtFuture {
32 
33 // Inherit option from Qt6 is not supported in Qt5
34 enum class Launch
35 {
36  Sync,
37  Async,
38 };
39 
40 } // namespace QtFuture
41 
42 namespace QtPrivate {
43 
44 template <typename...>
45 struct ArgsType;
46 
47 template <typename Arg, typename... Args>
48 struct ArgsType<Arg, Args...>
49 {
50  using First = Arg;
51  using PromiseType = void;
52  using IsPromise = std::false_type;
53  static const bool HasExtraArgs = (sizeof...(Args) > 0);
54 
55  template <class Class, class Callable>
56  static const bool CanInvokeWithArgs =
57  std::is_invocable_v<Callable, Class, Arg, Args...>;
58 };
59 
60 template <typename Arg, typename... Args>
61 struct ArgsType<QPromise<Arg> &, Args...>
62 {
63  using First = QPromise<Arg> &;
64  using PromiseType = Arg;
65  using IsPromise = std::true_type;
66  static const bool HasExtraArgs = (sizeof...(Args) > 0);
67 
68  template <class Class, class Callable>
69  static const bool CanInvokeWithArgs =
70  std::is_invocable_v<Callable, Class, QPromise<Arg> &, Args...>;
71 };
72 
73 template <>
74 struct ArgsType<>
75 {
76  using First = void;
77  using PromiseType = void;
78  using IsPromise = std::false_type;
79  static const bool HasExtraArgs = false;
80  using AllArgs = void;
81 
82  template <class Class, class Callable>
83  static const bool CanInvokeWithArgs = std::is_invocable_v<Callable, Class>;
84 };
85 
86 template <typename F>
87 struct ArgResolver : ArgResolver<decltype(&std::decay_t<F>::operator())>
88 {};
89 
90 template <typename F>
91 struct ArgResolver<std::reference_wrapper<F>> :
92  ArgResolver<decltype(&std::decay_t<F>::operator())>
93 {};
94 
95 template <typename R, typename... Args>
96 struct ArgResolver<R(Args...)> : public ArgsType<Args...>
97 {};
98 
99 template <typename R, typename... Args>
100 struct ArgResolver<R (*)(Args...)> : public ArgsType<Args...>
101 {};
102 
103 template <typename R, typename... Args>
104 struct ArgResolver<R (*&)(Args...)> : public ArgsType<Args...>
105 {};
106 
107 template <typename R, typename... Args>
108 struct ArgResolver<R (*const)(Args...)> : public ArgsType<Args...>
109 {};
110 
111 template <typename R, typename... Args>
112 struct ArgResolver<R (&)(Args...)> : public ArgsType<Args...>
113 {};
114 
115 template <typename Class, typename R, typename... Args>
116 struct ArgResolver<R (Class::*)(Args...)> : public ArgsType<Args...>
117 {};
118 
119 template <typename Class, typename R, typename... Args>
120 struct ArgResolver<R (Class::*)(Args...) noexcept> : public ArgsType<Args...>
121 {};
122 
123 template <typename Class, typename R, typename... Args>
124 struct ArgResolver<R (Class::*)(Args...) const> : public ArgsType<Args...>
125 {};
126 
127 template <typename Class, typename R, typename... Args>
128 struct ArgResolver<R (Class::*)(Args...) const noexcept> :
129  public ArgsType<Args...>
130 {};
131 
132 template <typename Class, typename R, typename... Args>
133 struct ArgResolver<R (Class::*const)(Args...) const> : public ArgsType<Args...>
134 {};
135 
136 template <typename Class, typename R, typename... Args>
137 struct ArgResolver<R (Class::*const)(Args...) const noexcept> :
138  public ArgsType<Args...>
139 {};
140 
141 } // namespace QtPrivate
142 #endif // QT_VERSION
143 
144 namespace quentier::threading::detail {
145 
146 template <typename F, typename Arg, typename Enable = void>
148 {};
149 
150 // The callable takes an argument of type Arg
151 template <typename F, typename Arg>
153  F, Arg,
154  typename std::enable_if_t<
155  !std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
156 {
157  using ResultType = std::invoke_result_t<std::decay_t<F>, std::decay_t<Arg>>;
158 };
159 
160 // The callable takes an argument of type QFuture<Arg>
161 template <class F, class Arg>
163  F, Arg,
164  typename std::enable_if_t<
165  std::is_invocable_v<std::decay_t<F>, QFuture<Arg>>>>
166 {
167  using ResultType = std::invoke_result_t<std::decay_t<F>, QFuture<Arg>>;
168 };
169 
170 // The callable takes an argument of type QFuture<void>
171 template <class F>
173  F, void,
174  typename std::enable_if_t<
175  std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
176 {
177  using ResultType = std::invoke_result_t<std::decay_t<F>, QFuture<void>>;
178 };
179 
180 // The callable doesn't take argument
181 template <class F>
183  F, void,
184  typename std::enable_if_t<
185  !std::is_invocable_v<std::decay_t<F>, QFuture<void>>>>
186 {
187  using ResultType = std::invoke_result_t<std::decay_t<F>>;
188 };
189 
190 } // namespace quentier::threading::detail
Definition: QtFutureContinuations.h:99
Definition: Qt5Promise.h:27
Definition: QtFutureHelpers.h:147