|
21 | 21 | #include "__meta.hpp" |
22 | 22 | #include "__query.hpp" |
23 | 23 | #include "__tag_invoke.hpp" |
| 24 | +#include "__tuple.hpp" |
24 | 25 |
|
25 | 26 | #include <exception> // IWYU pragma: keep for std::terminate |
26 | 27 | #include <functional> // IWYU pragma: keep for unwrap_reference_t |
|
29 | 30 | STDEXEC_PRAGMA_PUSH() |
30 | 31 | STDEXEC_PRAGMA_IGNORE_EDG(probable_guiding_friend) |
31 | 32 | STDEXEC_PRAGMA_IGNORE_EDG(type_qualifiers_ignored_on_reference) |
| 33 | +STDEXEC_PRAGMA_IGNORE_GNU("-Wmissing-braces") |
32 | 34 |
|
33 | 35 | namespace STDEXEC |
34 | 36 | { |
@@ -113,7 +115,7 @@ namespace STDEXEC |
113 | 115 | } |
114 | 116 | else |
115 | 117 | { |
116 | | - return env<_Env1, __fwd_env_t<_Env2>>{{static_cast<_Env1 &&>(__env1)}, |
| 118 | + return env<_Env1, __fwd_env_t<_Env2>>{static_cast<_Env1 &&>(__env1), |
117 | 119 | __fwd_fn()(static_cast<_Env2 &&>(__env2))}; |
118 | 120 | } |
119 | 121 | } |
@@ -201,70 +203,53 @@ namespace STDEXEC |
201 | 203 | STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE |
202 | 204 | prop(_Query, _Value) -> prop<_Query, std::unwrap_reference_t<_Value>>; |
203 | 205 |
|
204 | | - ////////////////////////////////////////////////////////////////////// |
205 | | - // env |
206 | | - template <class... _Envs> |
207 | | - struct env; |
208 | | - |
209 | | - template <> |
210 | | - struct env<> |
211 | | - { |
212 | | - STDEXEC_ATTRIBUTE(nodiscard, host, device) |
213 | | - auto query() const = delete; |
214 | | - }; |
215 | | - |
216 | | - template <class _Env> |
217 | | - struct env<_Env> : _Env |
218 | | - {}; |
219 | | - |
220 | | - template <class _Env> |
221 | | - struct env<_Env &> |
| 206 | + namespace __detail |
222 | 207 | { |
223 | 208 | template <class _Query, class... _Args> |
224 | | - requires __queryable_with<_Env, _Query, _Args...> |
225 | | - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) |
226 | | - constexpr auto query(_Query, _Args &&...__args) const |
227 | | - noexcept(__nothrow_queryable_with<_Env, _Query, _Args...>) |
228 | | - -> __query_result_t<_Env, _Query, _Args...> |
| 209 | + struct __get_1st_env |
229 | 210 | { |
230 | | - return __query<_Query>()(__env_, static_cast<_Args &&>(__args)...); |
231 | | - } |
| 211 | + STDEXEC_ATTRIBUTE(host, device, always_inline) |
| 212 | + constexpr void operator()() const noexcept {} |
232 | 213 |
|
233 | | - _Env &__env_; |
234 | | - }; |
| 214 | + template <class _Env0, class... _Envs> |
| 215 | + STDEXEC_ATTRIBUTE(host, device, always_inline) |
| 216 | + constexpr auto |
| 217 | + operator()(_Env0 const &__env0, _Envs const &...__envs) const noexcept -> decltype(auto) |
| 218 | + { |
| 219 | + if constexpr (__callable<__query<_Query>, _Env0 const &, _Args...>) |
| 220 | + return (__env0); // load-bearing parentheses, do not remove |
| 221 | + else |
| 222 | + return (*this)(__envs...); |
| 223 | + } |
| 224 | + }; |
| 225 | + } // namespace __detail |
235 | 226 |
|
236 | | - template <class _Env1, class _Env2> |
237 | | - struct env<_Env1, _Env2> |
| 227 | + ////////////////////////////////////////////////////////////////////// |
| 228 | + // env |
| 229 | + template <class... _Envs> |
| 230 | + struct env |
238 | 231 | { |
| 232 | + private: |
239 | 233 | template <class _Query, class... _Args> |
240 | | - requires __queryable_with<_Env1, _Query, _Args...> |
241 | | - STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) |
242 | | - constexpr auto query(_Query, _Args &&...__args) const |
243 | | - noexcept(__nothrow_queryable_with<_Env1, _Query, _Args...>) |
244 | | - -> __query_result_t<_Env1, _Query, _Args...> |
245 | | - { |
246 | | - return __query<_Query>()(__env1_, static_cast<_Args &&>(__args)...); |
247 | | - } |
| 234 | + using __1st_env_t = |
| 235 | + __call_result_t<__detail::__get_1st_env<_Query, _Args...>, _Envs const &...>; |
248 | 236 |
|
| 237 | + public: |
249 | 238 | template <class _Query, class... _Args> |
250 | | - requires __queryable_with<_Env1, _Query, _Args...> |
251 | | - || __queryable_with<_Env2, _Query, _Args...> |
| 239 | + requires __queryable_with<__1st_env_t<_Query, _Args...>, _Query, _Args...> |
252 | 240 | STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) |
253 | 241 | constexpr auto query(_Query, _Args &&...__args) const |
254 | | - noexcept(__nothrow_queryable_with<_Env2, _Query, _Args...>) |
255 | | - -> __query_result_t<_Env2, _Query, _Args...> |
| 242 | + noexcept(__nothrow_queryable_with<__1st_env_t<_Query, _Args...>, _Query, _Args...>) |
| 243 | + -> __query_result_t<__1st_env_t<_Query, _Args...>, _Query, _Args...> |
256 | 244 | { |
257 | | - return __query<_Query>()(__env2_, static_cast<_Args &&>(__args)...); |
| 245 | + auto const &__env = __apply(__detail::__get_1st_env<_Query, _Args...>(), __envs_); |
| 246 | + return __query<_Query>()(__env, static_cast<_Args &&>(__args)...); |
258 | 247 | } |
259 | 248 |
|
260 | | - STDEXEC_ATTRIBUTE(no_unique_address) _Env1 __env1_; |
261 | | - STDEXEC_ATTRIBUTE(no_unique_address) _Env2 __env2_; |
| 249 | + STDEXEC_ATTRIBUTE(no_unique_address) |
| 250 | + __tuple<_Envs...> __envs_; |
262 | 251 | }; |
263 | 252 |
|
264 | | - template <class _Env1, class _Env2, class... _Envs> |
265 | | - struct env<_Env1, _Env2, _Envs...> : env<env<_Env1, _Env2>, _Envs...> |
266 | | - {}; |
267 | | - |
268 | 253 | template <class... _Envs> |
269 | 254 | STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE env(_Envs...) -> env<std::unwrap_reference_t<_Envs>...>; |
270 | 255 |
|
|
0 commit comments