• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // execution/relationship.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 = is_executor<T>::value
164       || is_sender<T>::value || is_scheduler<T>::value);
165 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
166 
167   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
168   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
169   typedef relationship_t polymorphic_query_result_type;
170 
171   typedef detail::relationship::fork_t<I> fork_t;
172   typedef detail::relationship::continuation_t<I> continuation_t;
173 
174   BOOST_ASIO_CONSTEXPR relationship_t()
175     : value_(-1)
176   {
177   }
178 
179   BOOST_ASIO_CONSTEXPR relationship_t(fork_t)
180     : value_(0)
181   {
182   }
183 
184   BOOST_ASIO_CONSTEXPR relationship_t(continuation_t)
185     : value_(1)
186   {
187   }
188 
189 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
190   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
191   template <typename T>
192   static BOOST_ASIO_CONSTEXPR
193   typename traits::query_static_constexpr_member<
194       T, relationship_t>::result_type
195   static_query()
196     BOOST_ASIO_NOEXCEPT_IF((
197       traits::query_static_constexpr_member<
198         T, relationship_t
199       >::is_noexcept))
200   {
201     return traits::query_static_constexpr_member<
202         T, relationship_t>::value();
203   }
204 
205   template <typename T>
206   static BOOST_ASIO_CONSTEXPR
207   typename traits::static_query<T, fork_t>::result_type
208   static_query(
209       typename enable_if<
210         !traits::query_static_constexpr_member<
211             T, relationship_t>::is_valid
212           && !traits::query_member<T, relationship_t>::is_valid
213           && traits::static_query<T, fork_t>::is_valid
214       >::type* = 0) BOOST_ASIO_NOEXCEPT
215   {
216     return traits::static_query<T, fork_t>::value();
217   }
218 
219   template <typename T>
220   static BOOST_ASIO_CONSTEXPR
221   typename traits::static_query<T, continuation_t>::result_type
222   static_query(
223       typename enable_if<
224         !traits::query_static_constexpr_member<
225             T, relationship_t>::is_valid
226           && !traits::query_member<T, relationship_t>::is_valid
227           && !traits::static_query<T, fork_t>::is_valid
228           && traits::static_query<T, continuation_t>::is_valid
229       >::type* = 0) BOOST_ASIO_NOEXCEPT
230   {
231     return traits::static_query<T, continuation_t>::value();
232   }
233 
234   template <typename E,
235       typename T = decltype(relationship_t::static_query<E>())>
236   static BOOST_ASIO_CONSTEXPR const T static_query_v
237     = relationship_t::static_query<E>();
238 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
239        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
240 
241   friend BOOST_ASIO_CONSTEXPR bool operator==(
242       const relationship_t& a, const relationship_t& b)
243   {
244     return a.value_ == b.value_;
245   }
246 
247   friend BOOST_ASIO_CONSTEXPR bool operator!=(
248       const relationship_t& a, const relationship_t& b)
249   {
250     return a.value_ != b.value_;
251   }
252 
253   struct convertible_from_relationship_t
254   {
255     BOOST_ASIO_CONSTEXPR convertible_from_relationship_t(relationship_t)
256     {
257     }
258   };
259 
260   template <typename Executor>
261   friend BOOST_ASIO_CONSTEXPR relationship_t query(
262       const Executor& ex, convertible_from_relationship_t,
263       typename enable_if<
264         can_query<const Executor&, fork_t>::value
265       >::type* = 0)
266 #if !defined(__clang__) // Clang crashes if noexcept is used here.
267 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
268     BOOST_ASIO_NOEXCEPT_IF((
269       is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value))
270 #else // defined(BOOST_ASIO_MSVC)
271     BOOST_ASIO_NOEXCEPT_IF((
272       is_nothrow_query<const Executor&, fork_t>::value))
273 #endif // defined(BOOST_ASIO_MSVC)
274 #endif // !defined(__clang__)
275   {
276     return boost::asio::query(ex, fork_t());
277   }
278 
279   template <typename Executor>
280   friend BOOST_ASIO_CONSTEXPR relationship_t query(
281       const Executor& ex, convertible_from_relationship_t,
282       typename enable_if<
283         !can_query<const Executor&, fork_t>::value
284           && can_query<const Executor&, continuation_t>::value
285       >::type* = 0)
286 #if !defined(__clang__) // Clang crashes if noexcept is used here.
287 #if defined(BOOST_ASIO_MSVC) // Visual C++ wants the type to be qualified.
288     BOOST_ASIO_NOEXCEPT_IF((
289       is_nothrow_query<const Executor&,
290         relationship_t<>::continuation_t>::value))
291 #else // defined(BOOST_ASIO_MSVC)
292     BOOST_ASIO_NOEXCEPT_IF((
293       is_nothrow_query<const Executor&, continuation_t>::value))
294 #endif // defined(BOOST_ASIO_MSVC)
295 #endif // !defined(__clang__)
296   {
297     return boost::asio::query(ex, continuation_t());
298   }
299 
300   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(fork_t, fork);
301   BOOST_ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(continuation_t, continuation);
302 
303 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
304   static const relationship_t instance;
305 #endif // !defined(BOOST_ASIO_HAS_CONSTEXPR)
306 
307 private:
308   int value_;
309 };
310 
311 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
312   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
313 template <int I> template <typename E, typename T>
314 const T relationship_t<I>::static_query_v;
315 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
316        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
317 
318 #if !defined(BOOST_ASIO_HAS_CONSTEXPR)
319 template <int I>
320 const relationship_t<I> relationship_t<I>::instance;
321 #endif
322 
323 template <int I>
324 const typename relationship_t<I>::fork_t
325 relationship_t<I>::fork;
326 
327 template <int I>
328 const typename relationship_t<I>::continuation_t
329 relationship_t<I>::continuation;
330 
331 namespace relationship {
332 
333 template <int I = 0>
334 struct fork_t
335 {
336 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
337   template <typename T>
338   BOOST_ASIO_STATIC_CONSTEXPR(bool,
339     is_applicable_property_v = is_executor<T>::value
340       || is_sender<T>::value || is_scheduler<T>::value);
341 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
342 
343   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
344   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
345   typedef relationship_t<I> polymorphic_query_result_type;
346 
347   BOOST_ASIO_CONSTEXPR fork_t()
348   {
349   }
350 
351 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
352   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
353   template <typename T>
354   static BOOST_ASIO_CONSTEXPR
355   typename traits::query_static_constexpr_member<T, fork_t>::result_type
356   static_query()
357     BOOST_ASIO_NOEXCEPT_IF((
358       traits::query_static_constexpr_member<T, fork_t>::is_noexcept))
359   {
360     return traits::query_static_constexpr_member<T, fork_t>::value();
361   }
362 
363   template <typename T>
364   static BOOST_ASIO_CONSTEXPR fork_t static_query(
365       typename enable_if<
366         !traits::query_static_constexpr_member<T, fork_t>::is_valid
367           && !traits::query_member<T, fork_t>::is_valid
368           && !traits::query_free<T, fork_t>::is_valid
369           && !can_query<T, continuation_t<I> >::value
370       >::type* = 0) BOOST_ASIO_NOEXCEPT
371   {
372     return fork_t();
373   }
374 
375   template <typename E, typename T = decltype(fork_t::static_query<E>())>
376   static BOOST_ASIO_CONSTEXPR const T static_query_v
377     = fork_t::static_query<E>();
378 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
379        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
380 
381   static BOOST_ASIO_CONSTEXPR relationship_t<I> value()
382   {
383     return fork_t();
384   }
385 
386   friend BOOST_ASIO_CONSTEXPR bool operator==(
387       const fork_t&, const fork_t&)
388   {
389     return true;
390   }
391 
392   friend BOOST_ASIO_CONSTEXPR bool operator!=(
393       const fork_t&, const fork_t&)
394   {
395     return false;
396   }
397 };
398 
399 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
400   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
401 template <int I> template <typename E, typename T>
402 const T fork_t<I>::static_query_v;
403 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
404        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
405 
406 template <int I = 0>
407 struct continuation_t
408 {
409 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
410   template <typename T>
411   BOOST_ASIO_STATIC_CONSTEXPR(bool,
412     is_applicable_property_v = is_executor<T>::value
413       || is_sender<T>::value || is_scheduler<T>::value);
414 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
415 
416   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
417   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
418   typedef relationship_t<I> polymorphic_query_result_type;
419 
420   BOOST_ASIO_CONSTEXPR continuation_t()
421   {
422   }
423 
424 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
425   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
426   template <typename T>
427   static BOOST_ASIO_CONSTEXPR
428   typename traits::query_static_constexpr_member<T, continuation_t>::result_type
429   static_query()
430     BOOST_ASIO_NOEXCEPT_IF((
431       traits::query_static_constexpr_member<T, continuation_t>::is_noexcept))
432   {
433     return traits::query_static_constexpr_member<T, continuation_t>::value();
434   }
435 
436   template <typename E,
437       typename T = decltype(continuation_t::static_query<E>())>
438   static BOOST_ASIO_CONSTEXPR const T static_query_v
439     = continuation_t::static_query<E>();
440 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
441        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
442 
443   static BOOST_ASIO_CONSTEXPR relationship_t<I> value()
444   {
445     return continuation_t();
446   }
447 
448   friend BOOST_ASIO_CONSTEXPR bool operator==(
449       const continuation_t&, const continuation_t&)
450   {
451     return true;
452   }
453 
454   friend BOOST_ASIO_CONSTEXPR bool operator!=(
455       const continuation_t&, const continuation_t&)
456   {
457     return false;
458   }
459 };
460 
461 #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
462   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
463 template <int I> template <typename E, typename T>
464 const T continuation_t<I>::static_query_v;
465 #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
466        //   && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
467 
468 } // namespace relationship
469 } // namespace detail
470 
471 typedef detail::relationship_t<> relationship_t;
472 
473 #if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
474 constexpr relationship_t relationship;
475 #else // defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
476 namespace { static const relationship_t&
477   relationship = relationship_t::instance; }
478 #endif
479 
480 } // namespace execution
481 
482 #if !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
483 
484 template <typename T>
485 struct is_applicable_property<T, execution::relationship_t>
486   : integral_constant<bool,
487       execution::is_executor<T>::value
488         || execution::is_sender<T>::value
489         || execution::is_scheduler<T>::value>
490 {
491 };
492 
493 template <typename T>
494 struct is_applicable_property<T, execution::relationship_t::fork_t>
495   : integral_constant<bool,
496       execution::is_executor<T>::value
497         || execution::is_sender<T>::value
498         || execution::is_scheduler<T>::value>
499 {
500 };
501 
502 template <typename T>
503 struct is_applicable_property<T, execution::relationship_t::continuation_t>
504   : integral_constant<bool,
505       execution::is_executor<T>::value
506         || execution::is_sender<T>::value
507         || execution::is_scheduler<T>::value>
508 {
509 };
510 
511 #endif // !defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
512 
513 namespace traits {
514 
515 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
516 
517 template <typename T>
518 struct query_free_default<T, execution::relationship_t,
519   typename enable_if<
520     can_query<T, execution::relationship_t::fork_t>::value
521   >::type>
522 {
523   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
524   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
525     (is_nothrow_query<T, execution::relationship_t::fork_t>::value));
526 
527   typedef execution::relationship_t result_type;
528 };
529 
530 template <typename T>
531 struct query_free_default<T, execution::relationship_t,
532   typename enable_if<
533     !can_query<T, execution::relationship_t::fork_t>::value
534       && can_query<T, execution::relationship_t::continuation_t>::value
535   >::type>
536 {
537   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
538   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
539     (is_nothrow_query<T, execution::relationship_t::continuation_t>::value));
540 
541   typedef execution::relationship_t result_type;
542 };
543 
544 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
545 
546 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
547   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
548 
549 template <typename T>
550 struct static_query<T, execution::relationship_t,
551   typename enable_if<
552     traits::query_static_constexpr_member<T,
553       execution::relationship_t>::is_valid
554   >::type>
555 {
556   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
557   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
558 
559   typedef typename traits::query_static_constexpr_member<T,
560     execution::relationship_t>::result_type result_type;
561 
562   static BOOST_ASIO_CONSTEXPR result_type value()
563   {
564     return traits::query_static_constexpr_member<T,
565       execution::relationship_t>::value();
566   }
567 };
568 
569 template <typename T>
570 struct static_query<T, execution::relationship_t,
571   typename enable_if<
572     !traits::query_static_constexpr_member<T,
573         execution::relationship_t>::is_valid
574       && !traits::query_member<T,
575         execution::relationship_t>::is_valid
576       && traits::static_query<T,
577         execution::relationship_t::fork_t>::is_valid
578   >::type>
579 {
580   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
581   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
582 
583   typedef typename traits::static_query<T,
584     execution::relationship_t::fork_t>::result_type result_type;
585 
586   static BOOST_ASIO_CONSTEXPR result_type value()
587   {
588     return traits::static_query<T,
589         execution::relationship_t::fork_t>::value();
590   }
591 };
592 
593 template <typename T>
594 struct static_query<T, execution::relationship_t,
595   typename enable_if<
596     !traits::query_static_constexpr_member<T,
597         execution::relationship_t>::is_valid
598       && !traits::query_member<T,
599         execution::relationship_t>::is_valid
600       && !traits::static_query<T,
601         execution::relationship_t::fork_t>::is_valid
602       && traits::static_query<T,
603         execution::relationship_t::continuation_t>::is_valid
604   >::type>
605 {
606   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
607   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
608 
609   typedef typename traits::static_query<T,
610     execution::relationship_t::continuation_t>::result_type result_type;
611 
612   static BOOST_ASIO_CONSTEXPR result_type value()
613   {
614     return traits::static_query<T,
615         execution::relationship_t::continuation_t>::value();
616   }
617 };
618 
619 template <typename T>
620 struct static_query<T, execution::relationship_t::fork_t,
621   typename enable_if<
622     traits::query_static_constexpr_member<T,
623       execution::relationship_t::fork_t>::is_valid
624   >::type>
625 {
626   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
627   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
628 
629   typedef typename traits::query_static_constexpr_member<T,
630     execution::relationship_t::fork_t>::result_type result_type;
631 
632   static BOOST_ASIO_CONSTEXPR result_type value()
633   {
634     return traits::query_static_constexpr_member<T,
635       execution::relationship_t::fork_t>::value();
636   }
637 };
638 
639 template <typename T>
640 struct static_query<T, execution::relationship_t::fork_t,
641   typename enable_if<
642     !traits::query_static_constexpr_member<T,
643         execution::relationship_t::fork_t>::is_valid
644       && !traits::query_member<T,
645         execution::relationship_t::fork_t>::is_valid
646       && !traits::query_free<T,
647         execution::relationship_t::fork_t>::is_valid
648       && !can_query<T, execution::relationship_t::continuation_t>::value
649   >::type>
650 {
651   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
652   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
653 
654   typedef execution::relationship_t::fork_t result_type;
655 
656   static BOOST_ASIO_CONSTEXPR result_type value()
657   {
658     return result_type();
659   }
660 };
661 
662 template <typename T>
663 struct static_query<T, execution::relationship_t::continuation_t,
664   typename enable_if<
665     traits::query_static_constexpr_member<T,
666       execution::relationship_t::continuation_t>::is_valid
667   >::type>
668 {
669   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
670   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
671 
672   typedef typename traits::query_static_constexpr_member<T,
673     execution::relationship_t::continuation_t>::result_type result_type;
674 
675   static BOOST_ASIO_CONSTEXPR result_type value()
676   {
677     return traits::query_static_constexpr_member<T,
678       execution::relationship_t::continuation_t>::value();
679   }
680 };
681 
682 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
683        //   || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
684 
685 #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
686 
687 template <typename T>
688 struct static_require<T, execution::relationship_t::fork_t,
689   typename enable_if<
690     static_query<T, execution::relationship_t::fork_t>::is_valid
691   >::type>
692 {
693   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
694     (is_same<typename static_query<T,
695       execution::relationship_t::fork_t>::result_type,
696         execution::relationship_t::fork_t>::value));
697 };
698 
699 template <typename T>
700 struct static_require<T, execution::relationship_t::continuation_t,
701   typename enable_if<
702     static_query<T, execution::relationship_t::continuation_t>::is_valid
703   >::type>
704 {
705   BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid =
706     (is_same<typename static_query<T,
707       execution::relationship_t::continuation_t>::result_type,
708         execution::relationship_t::continuation_t>::value));
709 };
710 
711 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
712 
713 } // namespace traits
714 
715 #endif // defined(GENERATING_DOCUMENTATION)
716 
717 } // namespace asio
718 } // namespace boost
719 
720 #include <boost/asio/detail/pop_options.hpp>
721 
722 #endif // BOOST_ASIO_EXECUTION_RELATIONSHIP_HPP
723