1//
2// execution/relationship.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_EXECUTION_RELATIONSHIP_HPP
12#define BOOST_ASIO_EXECUTION_RELATIONSHIP_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#include <boost/asio/execution/executor.hpp>
21#include <boost/asio/is_applicable_property.hpp>
22#include <boost/asio/query.hpp>
23#include <boost/asio/traits/query_free.hpp>
24#include <boost/asio/traits/query_member.hpp>
25#include <boost/asio/traits/query_static_constexpr_member.hpp>
26#include <boost/asio/traits/static_query.hpp>
27#include <boost/asio/traits/static_require.hpp>
28
29#include <boost/asio/detail/push_options.hpp>
30
31namespace boost {
32namespace asio {
33
34#if defined(GENERATING_DOCUMENTATION)
35
36namespace execution {
37
38/// A property to describe whether submitted tasks represent continuations of
39/// the calling context.
40struct relationship_t
41{
42 /// The relationship_t property applies to executors.
43 template <typename T>
44 static constexpr bool is_applicable_property_v = is_executor_v<T>;
45
46 /// The top-level relationship_t property cannot be required.
47 static constexpr bool is_requirable = false;
48
49 /// The top-level relationship_t property cannot be preferred.
50 static constexpr bool is_preferable = false;
51
52 /// The type returned by queries against an @c any_executor.
53 typedef relationship_t polymorphic_query_result_type;
54
55 /// A sub-property that indicates that the executor does not represent a
56 /// continuation of the calling context.
57 struct fork_t
58 {
59 /// The relationship_t::fork_t property applies to executors.
60 template <typename T>
61 static constexpr bool is_applicable_property_v = is_executor_v<T>;
62
63 /// The relationship_t::fork_t property can be required.
64 static constexpr bool is_requirable = true;
65
66 /// The relationship_t::fork_t property can be preferred.
67 static constexpr bool is_preferable = true;
68
69 /// The type returned by queries against an @c any_executor.
70 typedef relationship_t polymorphic_query_result_type;
71
72 /// Default constructor.
73 constexpr fork_t();
74
75 /// Get the value associated with a property object.
76 /**
77 * @returns fork_t();
78 */
79 static constexpr relationship_t value();
80 };
81
82 /// A sub-property that indicates that the executor represents a continuation
83 /// of the calling context.
84 struct continuation_t
85 {
86 /// The relationship_t::continuation_t property applies to executors.
87 template <typename T>
88 static constexpr bool is_applicable_property_v = is_executor_v<T>;
89
90 /// The relationship_t::continuation_t property can be required.
91 static constexpr bool is_requirable = true;
92
93 /// The relationship_t::continuation_t property can be preferred.
94 static constexpr bool is_preferable = true;
95
96 /// The type returned by queries against an @c any_executor.
97 typedef relationship_t polymorphic_query_result_type;
98
99 /// Default constructor.
100 constexpr continuation_t();
101
102 /// Get the value associated with a property object.
103 /**
104 * @returns continuation_t();
105 */
106 static constexpr relationship_t value();
107 };
108
109 /// A special value used for accessing the relationship_t::fork_t property.
110 static constexpr fork_t fork;
111
112 /// A special value used for accessing the relationship_t::continuation_t
113 /// property.
114 static constexpr continuation_t continuation;
115
116 /// Default constructor.
117 constexpr relationship_t();
118
119 /// Construct from a sub-property value.
120 constexpr relationship_t(fork_t);
121
122 /// Construct from a sub-property value.
123 constexpr relationship_t(continuation_t);
124
125 /// Compare property values for equality.
126 friend constexpr bool operator==(
127 const relationship_t& a, const relationship_t& b) noexcept;
128
129 /// Compare property values for inequality.
130 friend constexpr bool operator!=(
131 const relationship_t& a, const relationship_t& b) noexcept;
132};
133
134/// A special value used for accessing the relationship_t property.
135constexpr relationship_t relationship;
136
137} // namespace execution
138
139#else // defined(GENERATING_DOCUMENTATION)
140
141namespace execution {
142namespace detail {
143namespace relationship {
144
145template <int I> struct fork_t;
146template <int I> struct continuation_t;
147
148} // namespace relationship
149
150template <int I = 0>
151struct relationship_t
152{
153#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
154 template <typename T>
155 static constexpr bool is_applicable_property_v = is_executor<T>::value;
156#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
157
158 static constexpr bool is_requirable = false;
159 static constexpr bool is_preferable = false;
160 typedef relationship_t polymorphic_query_result_type;
161
162 typedef detail::relationship::fork_t<I> fork_t;
163 typedef detail::relationship::continuation_t<I> continuation_t;
164
165 constexpr relationship_t()
166 : value_(-1)
167 {
168 }
169
170 constexpr relationship_t(fork_t)
171 : value_(0)
172 {
173 }
174
175 constexpr relationship_t(continuation_t)
176 : value_(1)
177 {
178 }
179
180 template <typename T>
181 struct proxy
182 {
183#if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
184 struct type
185 {
186 template <typename P>
187 auto query(P&& p) const
188 noexcept(
189 noexcept(
190 declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
191 )
192 )
193 -> decltype(
194 declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
195 );
196 };
197#else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
198 typedef T type;
199#endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
200 };
201
202 template <typename T>
203 struct static_proxy
204 {
205#if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
206 struct type
207 {
208 template <typename P>
209 static constexpr auto query(P&& p)
210 noexcept(
211 noexcept(
212 conditional_t<true, T, P>::query(static_cast<P&&>(p))
213 )
214 )
215 -> decltype(
216 conditional_t<true, T, P>::query(static_cast<P&&>(p))
217 )
218 {
219 return T::query(static_cast<P&&>(p));
220 }
221 };
222#else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
223 typedef T type;
224#endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
225 };
226
227 template <typename T>
228 struct query_member :
229 traits::query_member<typename proxy<T>::type, relationship_t> {};
230
231 template <typename T>
232 struct query_static_constexpr_member :
233 traits::query_static_constexpr_member<
234 typename static_proxy<T>::type, relationship_t> {};
235
236#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
237 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
238 template <typename T>
239 static constexpr
240 typename query_static_constexpr_member<T>::result_type
241 static_query()
242 noexcept(query_static_constexpr_member<T>::is_noexcept)
243 {
244 return query_static_constexpr_member<T>::value();
245 }
246
247 template <typename T>
248 static constexpr
249 typename traits::static_query<T, fork_t>::result_type
250 static_query(
251 enable_if_t<
252 !query_static_constexpr_member<T>::is_valid
253 >* = 0,
254 enable_if_t<
255 !query_member<T>::is_valid
256 >* = 0,
257 enable_if_t<
258 traits::static_query<T, fork_t>::is_valid
259 >* = 0) noexcept
260 {
261 return traits::static_query<T, fork_t>::value();
262 }
263
264 template <typename T>
265 static constexpr
266 typename traits::static_query<T, continuation_t>::result_type
267 static_query(
268 enable_if_t<
269 !query_static_constexpr_member<T>::is_valid
270 >* = 0,
271 enable_if_t<
272 !query_member<T>::is_valid
273 >* = 0,
274 enable_if_t<
275 !traits::static_query<T, fork_t>::is_valid
276 >* = 0,
277 enable_if_t<
278 traits::static_query<T, continuation_t>::is_valid
279 >* = 0) noexcept
280 {
281 return traits::static_query<T, continuation_t>::value();
282 }
283
284 template <typename E,
285 typename T = decltype(relationship_t::static_query<E>())>
286 static constexpr const T static_query_v
287 = relationship_t::static_query<E>();
288#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
289 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
290
291 friend constexpr bool operator==(
292 const relationship_t& a, const relationship_t& b)
293 {
294 return a.value_ == b.value_;
295 }
296
297 friend constexpr bool operator!=(
298 const relationship_t& a, const relationship_t& b)
299 {
300 return a.value_ != b.value_;
301 }
302
303 struct convertible_from_relationship_t
304 {
305 constexpr convertible_from_relationship_t(relationship_t)
306 {
307 }
308 };
309
310 template <typename Executor>
311 friend constexpr relationship_t query(
312 const Executor& ex, convertible_from_relationship_t,
313 enable_if_t<
314 can_query<const Executor&, fork_t>::value
315 >* = 0)
316#if !defined(__clang__) // Clang crashes if noexcept is used here.
317#if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
318 noexcept(is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value)
319#else // defined(BOOST_ASIO_MSVC)
320 noexcept(is_nothrow_query<const Executor&, fork_t>::value)
321#endif // defined(BOOST_ASIO_MSVC)
322#endif // !defined(__clang__)
323 {
324 return boost::asio::query(ex, fork_t());
325 }
326
327 template <typename Executor>
328 friend constexpr relationship_t query(
329 const Executor& ex, convertible_from_relationship_t,
330 enable_if_t<
331 !can_query<const Executor&, fork_t>::value
332 >* = 0,
333 enable_if_t<
334 can_query<const Executor&, continuation_t>::value
335 >* = 0)
336#if !defined(__clang__) // Clang crashes if noexcept is used here.
337#if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
338 noexcept(is_nothrow_query<const Executor&,
339 relationship_t<>::continuation_t>::value)
340#else // defined(BOOST_ASIO_MSVC)
341 noexcept(is_nothrow_query<const Executor&, continuation_t>::value)
342#endif // defined(BOOST_ASIO_MSVC)
343#endif // !defined(__clang__)
344 {
345 return boost::asio::query(ex, continuation_t());
346 }
347
348 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(fork_t, fork);
349 BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(continuation_t, continuation);
350
351private:
352 int value_;
353};
354
355#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
356 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
357template <int I> template <typename E, typename T>
358const T relationship_t<I>::static_query_v;
359#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
360 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
361
362template <int I>
363const typename relationship_t<I>::fork_t relationship_t<I>::fork;
364
365template <int I>
366const typename relationship_t<I>::continuation_t
367relationship_t<I>::continuation;
368
369namespace relationship {
370
371template <int I = 0>
372struct fork_t
373{
374#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
375 template <typename T>
376 static constexpr bool is_applicable_property_v = is_executor<T>::value;
377#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
378
379 static constexpr bool is_requirable = true;
380 static constexpr bool is_preferable = true;
381 typedef relationship_t<I> polymorphic_query_result_type;
382
383 constexpr fork_t()
384 {
385 }
386
387 template <typename T>
388 struct query_member :
389 traits::query_member<
390 typename relationship_t<I>::template proxy<T>::type, fork_t> {};
391
392 template <typename T>
393 struct query_static_constexpr_member :
394 traits::query_static_constexpr_member<
395 typename relationship_t<I>::template static_proxy<T>::type, fork_t> {};
396
397#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
398 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
399 template <typename T>
400 static constexpr typename query_static_constexpr_member<T>::result_type
401 static_query()
402 noexcept(query_static_constexpr_member<T>::is_noexcept)
403 {
404 return query_static_constexpr_member<T>::value();
405 }
406
407 template <typename T>
408 static constexpr fork_t static_query(
409 enable_if_t<
410 !query_static_constexpr_member<T>::is_valid
411 >* = 0,
412 enable_if_t<
413 !query_member<T>::is_valid
414 >* = 0,
415 enable_if_t<
416 !traits::query_free<T, fork_t>::is_valid
417 >* = 0,
418 enable_if_t<
419 !can_query<T, continuation_t<I>>::value
420 >* = 0) noexcept
421 {
422 return fork_t();
423 }
424
425 template <typename E, typename T = decltype(fork_t::static_query<E>())>
426 static constexpr const T static_query_v
427 = fork_t::static_query<E>();
428#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
429 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
430
431 static constexpr relationship_t<I> value()
432 {
433 return fork_t();
434 }
435
436 friend constexpr bool operator==(const fork_t&, const fork_t&)
437 {
438 return true;
439 }
440
441 friend constexpr bool operator!=(const fork_t&, const fork_t&)
442 {
443 return false;
444 }
445
446 friend constexpr bool operator==(const fork_t&, const continuation_t<I>&)
447 {
448 return false;
449 }
450
451 friend constexpr bool operator!=(const fork_t&, const continuation_t<I>&)
452 {
453 return true;
454 }
455};
456
457#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
458 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
459template <int I> template <typename E, typename T>
460const T fork_t<I>::static_query_v;
461#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
462 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
463
464template <int I = 0>
465struct continuation_t
466{
467#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
468 template <typename T>
469 static constexpr bool is_applicable_property_v = is_executor<T>::value;
470#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
471
472 static constexpr bool is_requirable = true;
473 static constexpr bool is_preferable = true;
474 typedef relationship_t<I> polymorphic_query_result_type;
475
476 constexpr continuation_t()
477 {
478 }
479
480 template <typename T>
481 struct query_member :
482 traits::query_member<
483 typename relationship_t<I>::template proxy<T>::type, continuation_t> {};
484
485 template <typename T>
486 struct query_static_constexpr_member :
487 traits::query_static_constexpr_member<
488 typename relationship_t<I>::template static_proxy<T>::type,
489 continuation_t> {};
490
491#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
492 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
493 template <typename T>
494 static constexpr typename query_static_constexpr_member<T>::result_type
495 static_query()
496 noexcept(query_static_constexpr_member<T>::is_noexcept)
497 {
498 return query_static_constexpr_member<T>::value();
499 }
500
501 template <typename E,
502 typename T = decltype(continuation_t::static_query<E>())>
503 static constexpr const T static_query_v
504 = continuation_t::static_query<E>();
505#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
506 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
507
508 static constexpr relationship_t<I> value()
509 {
510 return continuation_t();
511 }
512
513 friend constexpr bool operator==(const continuation_t&, const continuation_t&)
514 {
515 return true;
516 }
517
518 friend constexpr bool operator!=(const continuation_t&, const continuation_t&)
519 {
520 return false;
521 }
522
523 friend constexpr bool operator==(const continuation_t&, const fork_t<I>&)
524 {
525 return false;
526 }
527
528 friend constexpr bool operator!=(const continuation_t&, const fork_t<I>&)
529 {
530 return true;
531 }
532};
533
534#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
535 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
536template <int I> template <typename E, typename T>
537const T continuation_t<I>::static_query_v;
538#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
539 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
540
541} // namespace relationship
542} // namespace detail
543
544typedef detail::relationship_t<> relationship_t;
545
546constexpr relationship_t relationship;
547
548} // namespace execution
549
550#if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
551
552template <typename T>
553struct is_applicable_property<T, execution::relationship_t>
554 : integral_constant<bool, execution::is_executor<T>::value>
555{
556};
557
558template <typename T>
559struct is_applicable_property<T, execution::relationship_t::fork_t>
560 : integral_constant<bool, execution::is_executor<T>::value>
561{
562};
563
564template <typename T>
565struct is_applicable_property<T, execution::relationship_t::continuation_t>
566 : integral_constant<bool, execution::is_executor<T>::value>
567{
568};
569
570#endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
571
572namespace traits {
573
574#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
575
576template <typename T>
577struct query_free_default<T, execution::relationship_t,
578 enable_if_t<
579 can_query<T, execution::relationship_t::fork_t>::value
580 >>
581{
582 static constexpr bool is_valid = true;
583 static constexpr bool is_noexcept =
584 is_nothrow_query<T, execution::relationship_t::fork_t>::value;
585
586 typedef execution::relationship_t result_type;
587};
588
589template <typename T>
590struct query_free_default<T, execution::relationship_t,
591 enable_if_t<
592 !can_query<T, execution::relationship_t::fork_t>::value
593 && can_query<T, execution::relationship_t::continuation_t>::value
594 >>
595{
596 static constexpr bool is_valid = true;
597 static constexpr bool is_noexcept =
598 is_nothrow_query<T, execution::relationship_t::continuation_t>::value;
599
600 typedef execution::relationship_t result_type;
601};
602
603#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
604
605#if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
606 || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
607
608template <typename T>
609struct static_query<T, execution::relationship_t,
610 enable_if_t<
611 execution::detail::relationship_t<0>::
612 query_static_constexpr_member<T>::is_valid
613 >>
614{
615 static constexpr bool is_valid = true;
616 static constexpr bool is_noexcept = true;
617
618 typedef typename execution::detail::relationship_t<0>::
619 query_static_constexpr_member<T>::result_type result_type;
620
621 static constexpr result_type value()
622 {
623 return execution::detail::relationship_t<0>::
624 query_static_constexpr_member<T>::value();
625 }
626};
627
628template <typename T>
629struct static_query<T, execution::relationship_t,
630 enable_if_t<
631 !execution::detail::relationship_t<0>::
632 query_static_constexpr_member<T>::is_valid
633 && !execution::detail::relationship_t<0>::
634 query_member<T>::is_valid
635 && traits::static_query<T,
636 execution::relationship_t::fork_t>::is_valid
637 >>
638{
639 static constexpr bool is_valid = true;
640 static constexpr bool is_noexcept = true;
641
642 typedef typename traits::static_query<T,
643 execution::relationship_t::fork_t>::result_type result_type;
644
645 static constexpr result_type value()
646 {
647 return traits::static_query<T,
648 execution::relationship_t::fork_t>::value();
649 }
650};
651
652template <typename T>
653struct static_query<T, execution::relationship_t,
654 enable_if_t<
655 !execution::detail::relationship_t<0>::
656 query_static_constexpr_member<T>::is_valid
657 && !execution::detail::relationship_t<0>::
658 query_member<T>::is_valid
659 && !traits::static_query<T,
660 execution::relationship_t::fork_t>::is_valid
661 && traits::static_query<T,
662 execution::relationship_t::continuation_t>::is_valid
663 >>
664{
665 static constexpr bool is_valid = true;
666 static constexpr bool is_noexcept = true;
667
668 typedef typename traits::static_query<T,
669 execution::relationship_t::continuation_t>::result_type result_type;
670
671 static constexpr result_type value()
672 {
673 return traits::static_query<T,
674 execution::relationship_t::continuation_t>::value();
675 }
676};
677
678template <typename T>
679struct static_query<T, execution::relationship_t::fork_t,
680 enable_if_t<
681 execution::detail::relationship::fork_t<0>::
682 query_static_constexpr_member<T>::is_valid
683 >>
684{
685 static constexpr bool is_valid = true;
686 static constexpr bool is_noexcept = true;
687
688 typedef typename execution::detail::relationship::fork_t<0>::
689 query_static_constexpr_member<T>::result_type result_type;
690
691 static constexpr result_type value()
692 {
693 return execution::detail::relationship::fork_t<0>::
694 query_static_constexpr_member<T>::value();
695 }
696};
697
698template <typename T>
699struct static_query<T, execution::relationship_t::fork_t,
700 enable_if_t<
701 !execution::detail::relationship::fork_t<0>::
702 query_static_constexpr_member<T>::is_valid
703 && !execution::detail::relationship::fork_t<0>::
704 query_member<T>::is_valid
705 && !traits::query_free<T,
706 execution::relationship_t::fork_t>::is_valid
707 && !can_query<T, execution::relationship_t::continuation_t>::value
708 >>
709{
710 static constexpr bool is_valid = true;
711 static constexpr bool is_noexcept = true;
712
713 typedef execution::relationship_t::fork_t result_type;
714
715 static constexpr result_type value()
716 {
717 return result_type();
718 }
719};
720
721template <typename T>
722struct static_query<T, execution::relationship_t::continuation_t,
723 enable_if_t<
724 execution::detail::relationship::continuation_t<0>::
725 query_static_constexpr_member<T>::is_valid
726 >>
727{
728 static constexpr bool is_valid = true;
729 static constexpr bool is_noexcept = true;
730
731 typedef typename execution::detail::relationship::continuation_t<0>::
732 query_static_constexpr_member<T>::result_type result_type;
733
734 static constexpr result_type value()
735 {
736 return execution::detail::relationship::continuation_t<0>::
737 query_static_constexpr_member<T>::value();
738 }
739};
740
741#endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
742 // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
743
744} // namespace traits
745
746#endif // defined(GENERATING_DOCUMENTATION)
747
748} // namespace asio
749} // namespace boost
750
751#include <boost/asio/detail/pop_options.hpp>
752
753#endif // BOOST_ASIO_EXECUTION_RELATIONSHIP_HPP
754

source code of boost/libs/asio/include/boost/asio/execution/relationship.hpp