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