1 | // |
2 | // async_result.hpp |
3 | // ~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
6 | // |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
9 | // |
10 | |
11 | #ifndef BOOST_ASIO_ASYNC_RESULT_HPP |
12 | #define BOOST_ASIO_ASYNC_RESULT_HPP |
13 | |
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
15 | # pragma once |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
17 | |
18 | #include <boost/asio/detail/config.hpp> |
19 | #include <boost/asio/detail/type_traits.hpp> |
20 | |
21 | #include <boost/asio/detail/push_options.hpp> |
22 | |
23 | namespace boost { |
24 | namespace asio { |
25 | |
26 | #if defined(BOOST_ASIO_HAS_CONCEPTS) |
27 | |
28 | namespace detail { |
29 | |
30 | template <typename T> |
31 | struct is_completion_signature : false_type |
32 | { |
33 | }; |
34 | |
35 | template <typename R, typename... Args> |
36 | struct is_completion_signature<R(Args...)> : true_type |
37 | { |
38 | }; |
39 | |
40 | template <typename R, typename... Args> |
41 | struct is_completion_signature<R(Args...) &> : true_type |
42 | { |
43 | }; |
44 | |
45 | template <typename R, typename... Args> |
46 | struct is_completion_signature<R(Args...) &&> : true_type |
47 | { |
48 | }; |
49 | |
50 | # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
51 | |
52 | template <typename R, typename... Args> |
53 | struct is_completion_signature<R(Args...) noexcept> : true_type |
54 | { |
55 | }; |
56 | |
57 | template <typename R, typename... Args> |
58 | struct is_completion_signature<R(Args...) & noexcept> : true_type |
59 | { |
60 | }; |
61 | |
62 | template <typename R, typename... Args> |
63 | struct is_completion_signature<R(Args...) && noexcept> : true_type |
64 | { |
65 | }; |
66 | |
67 | # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
68 | |
69 | template <typename... T> |
70 | struct are_completion_signatures : false_type |
71 | { |
72 | }; |
73 | |
74 | template <typename T0> |
75 | struct are_completion_signatures<T0> |
76 | : is_completion_signature<T0> |
77 | { |
78 | }; |
79 | |
80 | template <typename T0, typename... TN> |
81 | struct are_completion_signatures<T0, TN...> |
82 | : integral_constant<bool, ( |
83 | is_completion_signature<T0>::value |
84 | && are_completion_signatures<TN...>::value)> |
85 | { |
86 | }; |
87 | |
88 | template <typename T, typename... Args> |
89 | BOOST_ASIO_CONCEPT callable_with = requires(T&& t, Args&&... args) |
90 | { |
91 | static_cast<T&&>(t)(static_cast<Args&&>(args)...); |
92 | }; |
93 | |
94 | template <typename T, typename... Signatures> |
95 | struct is_completion_handler_for : false_type |
96 | { |
97 | }; |
98 | |
99 | template <typename T, typename R, typename... Args> |
100 | struct is_completion_handler_for<T, R(Args...)> |
101 | : integral_constant<bool, (callable_with<decay_t<T>, Args...>)> |
102 | { |
103 | }; |
104 | |
105 | template <typename T, typename R, typename... Args> |
106 | struct is_completion_handler_for<T, R(Args...) &> |
107 | : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)> |
108 | { |
109 | }; |
110 | |
111 | template <typename T, typename R, typename... Args> |
112 | struct is_completion_handler_for<T, R(Args...) &&> |
113 | : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)> |
114 | { |
115 | }; |
116 | |
117 | # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
118 | |
119 | template <typename T, typename R, typename... Args> |
120 | struct is_completion_handler_for<T, R(Args...) noexcept> |
121 | : integral_constant<bool, (callable_with<decay_t<T>, Args...>)> |
122 | { |
123 | }; |
124 | |
125 | template <typename T, typename R, typename... Args> |
126 | struct is_completion_handler_for<T, R(Args...) & noexcept> |
127 | : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)> |
128 | { |
129 | }; |
130 | |
131 | template <typename T, typename R, typename... Args> |
132 | struct is_completion_handler_for<T, R(Args...) && noexcept> |
133 | : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)> |
134 | { |
135 | }; |
136 | |
137 | # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
138 | |
139 | template <typename T, typename Signature0, typename... SignatureN> |
140 | struct is_completion_handler_for<T, Signature0, SignatureN...> |
141 | : integral_constant<bool, ( |
142 | is_completion_handler_for<T, Signature0>::value |
143 | && is_completion_handler_for<T, SignatureN...>::value)> |
144 | { |
145 | }; |
146 | |
147 | } // namespace detail |
148 | |
149 | template <typename T> |
150 | BOOST_ASIO_CONCEPT completion_signature = |
151 | detail::is_completion_signature<T>::value; |
152 | |
153 | #define BOOST_ASIO_COMPLETION_SIGNATURE \ |
154 | ::boost::asio::completion_signature |
155 | |
156 | template <typename T, typename... Signatures> |
157 | BOOST_ASIO_CONCEPT completion_handler_for = |
158 | detail::are_completion_signatures<Signatures...>::value |
159 | && detail::is_completion_handler_for<T, Signatures...>::value; |
160 | |
161 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) \ |
162 | ::boost::asio::completion_handler_for<sig> |
163 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) \ |
164 | ::boost::asio::completion_handler_for<sig0, sig1> |
165 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) \ |
166 | ::boost::asio::completion_handler_for<sig0, sig1, sig2> |
167 | |
168 | #else // defined(BOOST_ASIO_HAS_CONCEPTS) |
169 | |
170 | #define BOOST_ASIO_COMPLETION_SIGNATURE typename |
171 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR(sig) typename |
172 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) typename |
173 | #define BOOST_ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename |
174 | |
175 | #endif // defined(BOOST_ASIO_HAS_CONCEPTS) |
176 | |
177 | namespace detail { |
178 | |
179 | template <typename T> |
180 | struct is_lvalue_completion_signature : false_type |
181 | { |
182 | }; |
183 | |
184 | template <typename R, typename... Args> |
185 | struct is_lvalue_completion_signature<R(Args...) &> : true_type |
186 | { |
187 | }; |
188 | |
189 | # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
190 | |
191 | template <typename R, typename... Args> |
192 | struct is_lvalue_completion_signature<R(Args...) & noexcept> : true_type |
193 | { |
194 | }; |
195 | |
196 | # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
197 | |
198 | template <typename... Signatures> |
199 | struct are_any_lvalue_completion_signatures : false_type |
200 | { |
201 | }; |
202 | |
203 | template <typename Sig0> |
204 | struct are_any_lvalue_completion_signatures<Sig0> |
205 | : is_lvalue_completion_signature<Sig0> |
206 | { |
207 | }; |
208 | |
209 | template <typename Sig0, typename... SigN> |
210 | struct are_any_lvalue_completion_signatures<Sig0, SigN...> |
211 | : integral_constant<bool, ( |
212 | is_lvalue_completion_signature<Sig0>::value |
213 | || are_any_lvalue_completion_signatures<SigN...>::value)> |
214 | { |
215 | }; |
216 | |
217 | template <typename T> |
218 | struct is_rvalue_completion_signature : false_type |
219 | { |
220 | }; |
221 | |
222 | template <typename R, typename... Args> |
223 | struct is_rvalue_completion_signature<R(Args...) &&> : true_type |
224 | { |
225 | }; |
226 | |
227 | # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
228 | |
229 | template <typename R, typename... Args> |
230 | struct is_rvalue_completion_signature<R(Args...) && noexcept> : true_type |
231 | { |
232 | }; |
233 | |
234 | # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
235 | |
236 | template <typename... Signatures> |
237 | struct are_any_rvalue_completion_signatures : false_type |
238 | { |
239 | }; |
240 | |
241 | template <typename Sig0> |
242 | struct are_any_rvalue_completion_signatures<Sig0> |
243 | : is_rvalue_completion_signature<Sig0> |
244 | { |
245 | }; |
246 | |
247 | template <typename Sig0, typename... SigN> |
248 | struct are_any_rvalue_completion_signatures<Sig0, SigN...> |
249 | : integral_constant<bool, ( |
250 | is_rvalue_completion_signature<Sig0>::value |
251 | || are_any_rvalue_completion_signatures<SigN...>::value)> |
252 | { |
253 | }; |
254 | |
255 | template <typename T> |
256 | struct simple_completion_signature; |
257 | |
258 | template <typename R, typename... Args> |
259 | struct simple_completion_signature<R(Args...)> |
260 | { |
261 | typedef R type(Args...); |
262 | }; |
263 | |
264 | template <typename R, typename... Args> |
265 | struct simple_completion_signature<R(Args...) &> |
266 | { |
267 | typedef R type(Args...); |
268 | }; |
269 | |
270 | template <typename R, typename... Args> |
271 | struct simple_completion_signature<R(Args...) &&> |
272 | { |
273 | typedef R type(Args...); |
274 | }; |
275 | |
276 | # if defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
277 | |
278 | template <typename R, typename... Args> |
279 | struct simple_completion_signature<R(Args...) noexcept> |
280 | { |
281 | typedef R type(Args...); |
282 | }; |
283 | |
284 | template <typename R, typename... Args> |
285 | struct simple_completion_signature<R(Args...) & noexcept> |
286 | { |
287 | typedef R type(Args...); |
288 | }; |
289 | |
290 | template <typename R, typename... Args> |
291 | struct simple_completion_signature<R(Args...) && noexcept> |
292 | { |
293 | typedef R type(Args...); |
294 | }; |
295 | |
296 | # endif // defined(BOOST_ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) |
297 | |
298 | template <typename CompletionToken, |
299 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
300 | class completion_handler_async_result |
301 | { |
302 | public: |
303 | typedef CompletionToken completion_handler_type; |
304 | typedef void return_type; |
305 | |
306 | explicit completion_handler_async_result(completion_handler_type&) |
307 | { |
308 | } |
309 | |
310 | return_type get() |
311 | { |
312 | } |
313 | |
314 | template <typename Initiation, |
315 | BOOST_ASIO_COMPLETION_HANDLER_FOR(Signatures...) RawCompletionToken, |
316 | typename... Args> |
317 | static return_type initiate(Initiation&& initiation, |
318 | RawCompletionToken&& token, Args&&... args) |
319 | { |
320 | static_cast<Initiation&&>(initiation)( |
321 | static_cast<RawCompletionToken&&>(token), |
322 | static_cast<Args&&>(args)...); |
323 | } |
324 | |
325 | private: |
326 | completion_handler_async_result( |
327 | const completion_handler_async_result&) = delete; |
328 | completion_handler_async_result& operator=( |
329 | const completion_handler_async_result&) = delete; |
330 | }; |
331 | |
332 | } // namespace detail |
333 | |
334 | #if defined(GENERATING_DOCUMENTATION) |
335 | |
336 | /// An interface for customising the behaviour of an initiating function. |
337 | /** |
338 | * The async_result traits class is used for determining: |
339 | * |
340 | * @li the concrete completion handler type to be called at the end of the |
341 | * asynchronous operation; |
342 | * |
343 | * @li the initiating function return type; and |
344 | * |
345 | * @li how the return value of the initiating function is obtained. |
346 | * |
347 | * The trait allows the handler and return types to be determined at the point |
348 | * where the specific completion handler signature is known. |
349 | * |
350 | * This template may be specialised for user-defined completion token types. |
351 | * The primary template assumes that the CompletionToken is the completion |
352 | * handler. |
353 | */ |
354 | template <typename CompletionToken, |
355 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
356 | class async_result |
357 | { |
358 | public: |
359 | /// The concrete completion handler type for the specific signature. |
360 | typedef CompletionToken completion_handler_type; |
361 | |
362 | /// The return type of the initiating function. |
363 | typedef void return_type; |
364 | |
365 | /// Construct an async result from a given handler. |
366 | /** |
367 | * When using a specalised async_result, the constructor has an opportunity |
368 | * to initialise some state associated with the completion handler, which is |
369 | * then returned from the initiating function. |
370 | */ |
371 | explicit async_result(completion_handler_type& h); |
372 | |
373 | /// Obtain the value to be returned from the initiating function. |
374 | return_type get(); |
375 | |
376 | /// Initiate the asynchronous operation that will produce the result, and |
377 | /// obtain the value to be returned from the initiating function. |
378 | template <typename Initiation, typename RawCompletionToken, typename... Args> |
379 | static return_type initiate( |
380 | Initiation&& initiation, |
381 | RawCompletionToken&& token, |
382 | Args&&... args); |
383 | |
384 | private: |
385 | async_result(const async_result&) = delete; |
386 | async_result& operator=(const async_result&) = delete; |
387 | }; |
388 | |
389 | #else // defined(GENERATING_DOCUMENTATION) |
390 | |
391 | template <typename CompletionToken, |
392 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
393 | class async_result : |
394 | public conditional_t< |
395 | detail::are_any_lvalue_completion_signatures<Signatures...>::value |
396 | || !detail::are_any_rvalue_completion_signatures<Signatures...>::value, |
397 | detail::completion_handler_async_result<CompletionToken, Signatures...>, |
398 | async_result<CompletionToken, |
399 | typename detail::simple_completion_signature<Signatures>::type...> |
400 | > |
401 | { |
402 | public: |
403 | typedef conditional_t< |
404 | detail::are_any_lvalue_completion_signatures<Signatures...>::value |
405 | || !detail::are_any_rvalue_completion_signatures<Signatures...>::value, |
406 | detail::completion_handler_async_result<CompletionToken, Signatures...>, |
407 | async_result<CompletionToken, |
408 | typename detail::simple_completion_signature<Signatures>::type...> |
409 | > base_type; |
410 | |
411 | using base_type::base_type; |
412 | |
413 | private: |
414 | async_result(const async_result&) = delete; |
415 | async_result& operator=(const async_result&) = delete; |
416 | }; |
417 | |
418 | template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
419 | class async_result<void, Signatures...> |
420 | { |
421 | // Empty. |
422 | }; |
423 | |
424 | #endif // defined(GENERATING_DOCUMENTATION) |
425 | |
426 | /// Helper template to deduce the handler type from a CompletionToken, capture |
427 | /// a local copy of the handler, and then create an async_result for the |
428 | /// handler. |
429 | template <typename CompletionToken, |
430 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
431 | struct async_completion |
432 | { |
433 | /// The real handler type to be used for the asynchronous operation. |
434 | typedef typename boost::asio::async_result< |
435 | decay_t<CompletionToken>, Signatures...>::completion_handler_type |
436 | completion_handler_type; |
437 | |
438 | /// Constructor. |
439 | /** |
440 | * The constructor creates the concrete completion handler and makes the link |
441 | * between the handler and the asynchronous result. |
442 | */ |
443 | explicit async_completion(CompletionToken& token) |
444 | : completion_handler(static_cast<conditional_t< |
445 | is_same<CompletionToken, completion_handler_type>::value, |
446 | completion_handler_type&, CompletionToken&&>>(token)), |
447 | result(completion_handler) |
448 | { |
449 | } |
450 | |
451 | /// A copy of, or reference to, a real handler object. |
452 | conditional_t< |
453 | is_same<CompletionToken, completion_handler_type>::value, |
454 | completion_handler_type&, completion_handler_type> completion_handler; |
455 | |
456 | /// The result of the asynchronous operation's initiating function. |
457 | async_result<decay_t<CompletionToken>, Signatures...> result; |
458 | }; |
459 | |
460 | namespace detail { |
461 | |
462 | struct async_result_memfns_base |
463 | { |
464 | void initiate(); |
465 | }; |
466 | |
467 | template <typename T> |
468 | struct async_result_memfns_derived |
469 | : T, async_result_memfns_base |
470 | { |
471 | }; |
472 | |
473 | template <typename T, T> |
474 | struct async_result_memfns_check |
475 | { |
476 | }; |
477 | |
478 | template <typename> |
479 | char (&async_result_initiate_memfn_helper(...))[2]; |
480 | |
481 | template <typename T> |
482 | char async_result_initiate_memfn_helper( |
483 | async_result_memfns_check< |
484 | void (async_result_memfns_base::*)(), |
485 | &async_result_memfns_derived<T>::initiate>*); |
486 | |
487 | template <typename CompletionToken, |
488 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures> |
489 | struct async_result_has_initiate_memfn |
490 | : integral_constant<bool, sizeof(async_result_initiate_memfn_helper< |
491 | async_result<decay_t<CompletionToken>, Signatures...> |
492 | >(0)) != 1> |
493 | { |
494 | }; |
495 | |
496 | } // namespace detail |
497 | |
498 | #if defined(GENERATING_DOCUMENTATION) |
499 | # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ |
500 | void_or_deduced |
501 | # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \ |
502 | void_or_deduced |
503 | # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ |
504 | void_or_deduced |
505 | #else |
506 | # define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \ |
507 | typename ::boost::asio::async_result< \ |
508 | typename ::boost::asio::decay<ct>::type, sig>::return_type |
509 | # define BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \ |
510 | typename ::boost::asio::async_result< \ |
511 | typename ::boost::asio::decay<ct>::type, sig0, sig1>::return_type |
512 | # define BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ |
513 | typename ::boost::asio::async_result< \ |
514 | typename ::boost::asio::decay<ct>::type, sig0, sig1, sig2>::return_type |
515 | #define BOOST_ASIO_HANDLER_TYPE(ct, sig) \ |
516 | typename ::boost::asio::async_result< \ |
517 | typename ::boost::asio::decay<ct>::type, sig>::completion_handler_type |
518 | #define BOOST_ASIO_HANDLER_TYPE2(ct, sig0, sig1) \ |
519 | typename ::boost::asio::async_result< \ |
520 | typename ::boost::asio::decay<ct>::type, \ |
521 | sig0, sig1>::completion_handler_type |
522 | #define BOOST_ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \ |
523 | typename ::boost::asio::async_result< \ |
524 | typename ::boost::asio::decay<ct>::type, \ |
525 | sig0, sig1, sig2>::completion_handler_type |
526 | #endif |
527 | |
528 | #if defined(GENERATING_DOCUMENTATION) |
529 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ |
530 | auto |
531 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ |
532 | auto |
533 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ |
534 | auto |
535 | #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION) |
536 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ |
537 | auto |
538 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ |
539 | auto |
540 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ |
541 | auto |
542 | #else |
543 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \ |
544 | BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) |
545 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \ |
546 | BOOST_ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) |
547 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \ |
548 | BOOST_ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) |
549 | #endif |
550 | |
551 | #if defined(GENERATING_DOCUMENTATION) |
552 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ |
553 | auto |
554 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ |
555 | auto |
556 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ |
557 | auto |
558 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) |
559 | #elif defined(BOOST_ASIO_HAS_RETURN_TYPE_DEDUCTION) |
560 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ |
561 | auto |
562 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ |
563 | auto |
564 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ |
565 | auto |
566 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) |
567 | #else |
568 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ |
569 | auto |
570 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ |
571 | auto |
572 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ |
573 | auto |
574 | # define BOOST_ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr |
575 | #endif |
576 | |
577 | #if defined(GENERATING_DOCUMENTATION) |
578 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ |
579 | void_or_deduced |
580 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ |
581 | void_or_deduced |
582 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ |
583 | void_or_deduced |
584 | #else |
585 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ |
586 | decltype expr |
587 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ |
588 | decltype expr |
589 | # define BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ |
590 | decltype expr |
591 | #endif |
592 | |
593 | #if defined(GENERATING_DOCUMENTATION) |
594 | |
595 | template <typename CompletionToken, |
596 | completion_signature... Signatures, |
597 | typename Initiation, typename... Args> |
598 | void_or_deduced async_initiate( |
599 | Initiation&& initiation, |
600 | type_identity_t<CompletionToken>& token, |
601 | Args&&... args); |
602 | |
603 | #else // defined(GENERATING_DOCUMENTATION) |
604 | |
605 | template <typename CompletionToken, |
606 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures, |
607 | typename Initiation, typename... Args> |
608 | inline auto async_initiate(Initiation&& initiation, |
609 | type_identity_t<CompletionToken>& token, Args&&... args) |
610 | -> constraint_t< |
611 | detail::async_result_has_initiate_memfn< |
612 | CompletionToken, Signatures...>::value, |
613 | decltype( |
614 | async_result<decay_t<CompletionToken>, Signatures...>::initiate( |
615 | static_cast<Initiation&&>(initiation), |
616 | static_cast<CompletionToken&&>(token), |
617 | static_cast<Args&&>(args)...))> |
618 | { |
619 | return async_result<decay_t<CompletionToken>, Signatures...>::initiate( |
620 | static_cast<Initiation&&>(initiation), |
621 | static_cast<CompletionToken&&>(token), |
622 | static_cast<Args&&>(args)...); |
623 | } |
624 | |
625 | template <typename CompletionToken, |
626 | BOOST_ASIO_COMPLETION_SIGNATURE... Signatures, |
627 | typename Initiation, typename... Args> |
628 | inline constraint_t< |
629 | !detail::async_result_has_initiate_memfn< |
630 | CompletionToken, Signatures...>::value, |
631 | typename async_result<decay_t<CompletionToken>, Signatures...>::return_type> |
632 | async_initiate(Initiation&& initiation, |
633 | type_identity_t<CompletionToken>& token, Args&&... args) |
634 | { |
635 | async_completion<CompletionToken, Signatures...> completion(token); |
636 | |
637 | static_cast<Initiation&&>(initiation)( |
638 | static_cast< |
639 | typename async_result<decay_t<CompletionToken>, |
640 | Signatures...>::completion_handler_type&&>( |
641 | completion.completion_handler), |
642 | static_cast<Args&&>(args)...); |
643 | |
644 | return completion.result.get(); |
645 | } |
646 | |
647 | #endif // defined(GENERATING_DOCUMENTATION) |
648 | |
649 | #if defined(BOOST_ASIO_HAS_CONCEPTS) |
650 | |
651 | namespace detail { |
652 | |
653 | template <typename... Signatures> |
654 | struct initiation_archetype |
655 | { |
656 | template <completion_handler_for<Signatures...> CompletionHandler> |
657 | void operator()(CompletionHandler&&) const |
658 | { |
659 | } |
660 | }; |
661 | |
662 | } // namespace detail |
663 | |
664 | template <typename T, typename... Signatures> |
665 | BOOST_ASIO_CONCEPT completion_token_for = |
666 | detail::are_completion_signatures<Signatures...>::value |
667 | && |
668 | requires(T&& t) |
669 | { |
670 | async_initiate<T, Signatures...>( |
671 | detail::initiation_archetype<Signatures...>{}, t); |
672 | }; |
673 | |
674 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) \ |
675 | ::boost::asio::completion_token_for<sig> |
676 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \ |
677 | ::boost::asio::completion_token_for<sig0, sig1> |
678 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \ |
679 | ::boost::asio::completion_token_for<sig0, sig1, sig2> |
680 | |
681 | #else // defined(BOOST_ASIO_HAS_CONCEPTS) |
682 | |
683 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR(sig) typename |
684 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename |
685 | #define BOOST_ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename |
686 | |
687 | #endif // defined(BOOST_ASIO_HAS_CONCEPTS) |
688 | |
689 | namespace detail { |
690 | |
691 | struct async_operation_probe {}; |
692 | struct async_operation_probe_result {}; |
693 | |
694 | template <typename Call, typename = void> |
695 | struct is_async_operation_call : false_type |
696 | { |
697 | }; |
698 | |
699 | template <typename Call> |
700 | struct is_async_operation_call<Call, |
701 | void_t< |
702 | enable_if_t< |
703 | is_same< |
704 | result_of_t<Call>, |
705 | async_operation_probe_result |
706 | >::value |
707 | > |
708 | > |
709 | > : true_type |
710 | { |
711 | }; |
712 | |
713 | } // namespace detail |
714 | |
715 | #if !defined(GENERATING_DOCUMENTATION) |
716 | |
717 | template <typename... Signatures> |
718 | class async_result<detail::async_operation_probe, Signatures...> |
719 | { |
720 | public: |
721 | typedef detail::async_operation_probe_result return_type; |
722 | |
723 | template <typename Initiation, typename... InitArgs> |
724 | static return_type initiate(Initiation&&, |
725 | detail::async_operation_probe, InitArgs&&...) |
726 | { |
727 | return return_type(); |
728 | } |
729 | }; |
730 | |
731 | #endif // !defined(GENERATING_DOCUMENTATION) |
732 | |
733 | #if defined(GENERATING_DOCUMENTATION) |
734 | |
735 | /// The is_async_operation trait detects whether a type @c T and arguments |
736 | /// @c Args... may be used to initiate an asynchronous operation. |
737 | /** |
738 | * Class template @c is_async_operation is a trait is derived from @c true_type |
739 | * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous |
740 | * operation, where @c token is an unspecified completion token type. Otherwise, |
741 | * @c is_async_operation is derived from @c false_type. |
742 | */ |
743 | template <typename T, typename... Args> |
744 | struct is_async_operation : integral_constant<bool, automatically_determined> |
745 | { |
746 | }; |
747 | |
748 | #else // defined(GENERATING_DOCUMENTATION) |
749 | |
750 | template <typename T, typename... Args> |
751 | struct is_async_operation : |
752 | detail::is_async_operation_call< |
753 | T(Args..., detail::async_operation_probe)> |
754 | { |
755 | }; |
756 | |
757 | #endif // defined(GENERATING_DOCUMENTATION) |
758 | |
759 | #if defined(BOOST_ASIO_HAS_CONCEPTS) |
760 | |
761 | template <typename T, typename... Args> |
762 | BOOST_ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value; |
763 | |
764 | #define BOOST_ASIO_ASYNC_OPERATION(t) \ |
765 | ::boost::asio::async_operation<t> |
766 | #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) \ |
767 | ::boost::asio::async_operation<t, a0> |
768 | #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) \ |
769 | ::boost::asio::async_operation<t, a0, a1> |
770 | #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \ |
771 | ::boost::asio::async_operation<t, a0, a1, a2> |
772 | |
773 | #else // defined(BOOST_ASIO_HAS_CONCEPTS) |
774 | |
775 | #define BOOST_ASIO_ASYNC_OPERATION(t) typename |
776 | #define BOOST_ASIO_ASYNC_OPERATION1(t, a0) typename |
777 | #define BOOST_ASIO_ASYNC_OPERATION2(t, a0, a1) typename |
778 | #define BOOST_ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename |
779 | |
780 | #endif // defined(BOOST_ASIO_HAS_CONCEPTS) |
781 | |
782 | namespace detail { |
783 | |
784 | struct completion_signature_probe {}; |
785 | |
786 | template <typename... T> |
787 | struct completion_signature_probe_result |
788 | { |
789 | template <template <typename...> class Op> |
790 | struct apply |
791 | { |
792 | typedef Op<T...> type; |
793 | }; |
794 | }; |
795 | |
796 | template <typename T> |
797 | struct completion_signature_probe_result<T> |
798 | { |
799 | typedef T type; |
800 | |
801 | template <template <typename...> class Op> |
802 | struct apply |
803 | { |
804 | typedef Op<T> type; |
805 | }; |
806 | }; |
807 | |
808 | template <> |
809 | struct completion_signature_probe_result<void> |
810 | { |
811 | template <template <typename...> class Op> |
812 | struct apply |
813 | { |
814 | typedef Op<> type; |
815 | }; |
816 | }; |
817 | |
818 | } // namespace detail |
819 | |
820 | #if !defined(GENERATING_DOCUMENTATION) |
821 | |
822 | template <typename... Signatures> |
823 | class async_result<detail::completion_signature_probe, Signatures...> |
824 | { |
825 | public: |
826 | typedef detail::completion_signature_probe_result<Signatures...> return_type; |
827 | |
828 | template <typename Initiation, typename... InitArgs> |
829 | static return_type initiate(Initiation&&, |
830 | detail::completion_signature_probe, InitArgs&&...) |
831 | { |
832 | return return_type(); |
833 | } |
834 | }; |
835 | |
836 | template <typename Signature> |
837 | class async_result<detail::completion_signature_probe, Signature> |
838 | { |
839 | public: |
840 | typedef detail::completion_signature_probe_result<Signature> return_type; |
841 | |
842 | template <typename Initiation, typename... InitArgs> |
843 | static return_type initiate(Initiation&&, |
844 | detail::completion_signature_probe, InitArgs&&...) |
845 | { |
846 | return return_type(); |
847 | } |
848 | }; |
849 | |
850 | #endif // !defined(GENERATING_DOCUMENTATION) |
851 | |
852 | #if defined(GENERATING_DOCUMENTATION) |
853 | |
854 | /// The completion_signature_of trait determines the completion signature |
855 | /// of an asynchronous operation. |
856 | /** |
857 | * Class template @c completion_signature_of is a trait with a member type |
858 | * alias @c type that denotes the completion signature of the asynchronous |
859 | * operation initiated by the expression <tt>T(Args..., token)</tt> operation, |
860 | * where @c token is an unspecified completion token type. If the asynchronous |
861 | * operation does not have exactly one completion signature, the instantion of |
862 | * the trait is well-formed but the member type alias @c type is omitted. If |
863 | * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation |
864 | * then use of the trait is ill-formed. |
865 | */ |
866 | template <typename T, typename... Args> |
867 | struct completion_signature_of |
868 | { |
869 | typedef automatically_determined type; |
870 | }; |
871 | |
872 | #else // defined(GENERATING_DOCUMENTATION) |
873 | |
874 | template <typename T, typename... Args> |
875 | struct completion_signature_of : |
876 | result_of_t<T(Args..., detail::completion_signature_probe)> |
877 | { |
878 | }; |
879 | |
880 | #endif // defined(GENERATING_DOCUMENTATION) |
881 | |
882 | template <typename T, typename... Args> |
883 | using completion_signature_of_t = |
884 | typename completion_signature_of<T, Args...>::type; |
885 | |
886 | namespace detail { |
887 | |
888 | template <typename T, typename = void> |
889 | struct default_completion_token_impl |
890 | { |
891 | typedef void type; |
892 | }; |
893 | |
894 | template <typename T> |
895 | struct default_completion_token_impl<T, |
896 | void_t<typename T::default_completion_token_type> |
897 | > |
898 | { |
899 | typedef typename T::default_completion_token_type type; |
900 | }; |
901 | |
902 | } // namespace detail |
903 | |
904 | #if defined(GENERATING_DOCUMENTATION) |
905 | |
906 | /// Traits type used to determine the default completion token type associated |
907 | /// with a type (such as an executor). |
908 | /** |
909 | * A program may specialise this traits type if the @c T template parameter in |
910 | * the specialisation is a user-defined type. |
911 | * |
912 | * Specialisations of this trait may provide a nested typedef @c type, which is |
913 | * a default-constructible completion token type. |
914 | */ |
915 | template <typename T> |
916 | struct default_completion_token |
917 | { |
918 | /// If @c T has a nested type @c default_completion_token_type, |
919 | /// <tt>T::default_completion_token_type</tt>. Otherwise the typedef @c type |
920 | /// is not defined. |
921 | typedef see_below type; |
922 | }; |
923 | #else |
924 | template <typename T> |
925 | struct default_completion_token |
926 | : detail::default_completion_token_impl<T> |
927 | { |
928 | }; |
929 | #endif |
930 | |
931 | template <typename T> |
932 | using default_completion_token_t = typename default_completion_token<T>::type; |
933 | |
934 | #define BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(e) \ |
935 | = typename ::boost::asio::default_completion_token<e>::type |
936 | #define BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(e) \ |
937 | = typename ::boost::asio::default_completion_token<e>::type() |
938 | |
939 | } // namespace asio |
940 | } // namespace boost |
941 | |
942 | #include <boost/asio/detail/pop_options.hpp> |
943 | |
944 | #endif // BOOST_ASIO_ASYNC_RESULT_HPP |
945 | |