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