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