1 // 2 // prefer.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_PREFER_HPP 12 #define BOOST_ASIO_PREFER_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/is_applicable_property.hpp> 21 #include <boost/asio/traits/prefer_free.hpp> 22 #include <boost/asio/traits/prefer_member.hpp> 23 #include <boost/asio/traits/require_free.hpp> 24 #include <boost/asio/traits/require_member.hpp> 25 #include <boost/asio/traits/static_require.hpp> 26 27 #include <boost/asio/detail/push_options.hpp> 28 29 #if defined(GENERATING_DOCUMENTATION) 30 31 namespace boost { 32 namespace asio { 33 34 /// A customisation point that attempts to apply a property to an object. 35 /** 36 * The name <tt>prefer</tt> denotes a customisation point object. The 37 * expression <tt>boost::asio::prefer(E, P0, Pn...)</tt> for some subexpressions 38 * <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt> represents <tt>N</tt> 39 * subexpressions (where <tt>N</tt> is 0 or more, and with types <tt>T = 40 * decay_t<decltype(E)></tt> and <tt>Prop0 = decay_t<decltype(P0)></tt>) is 41 * expression-equivalent to: 42 * 43 * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_preferable</tt> is 44 * not a well-formed constant expression with value <tt>true</tt>, 45 * <tt>boost::asio::prefer(E, P0, Pn...)</tt> is ill-formed. 46 * 47 * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt> and the expression 48 * <tt>Prop0::template static_query_v<T> == Prop0::value()</tt> is a 49 * well-formed constant expression with value <tt>true</tt>. 50 * 51 * @li Otherwise, <tt>(E).require(P0)</tt> if <tt>N == 0</tt> and the expression 52 * <tt>(E).require(P0)</tt> is a valid expression. 53 * 54 * @li Otherwise, <tt>require(E, P0)</tt> if <tt>N == 0</tt> and the expression 55 * <tt>require(E, P0)</tt> is a valid expression with overload resolution 56 * performed in a context that does not include the declaration of the 57 * <tt>require</tt> customization point object. 58 * 59 * @li Otherwise, <tt>(E).prefer(P0)</tt> if <tt>N == 0</tt> and the expression 60 * <tt>(E).prefer(P0)</tt> is a valid expression. 61 * 62 * @li Otherwise, <tt>prefer(E, P0)</tt> if <tt>N == 0</tt> and the expression 63 * <tt>prefer(E, P0)</tt> is a valid expression with overload resolution 64 * performed in a context that does not include the declaration of the 65 * <tt>prefer</tt> customization point object. 66 * 67 * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt>. 68 * 69 * @li Otherwise, 70 * <tt>boost::asio::prefer(boost::asio::prefer(E, P0), Pn...)</tt> 71 * if <tt>N > 0</tt> and the expression 72 * <tt>boost::asio::prefer(boost::asio::prefer(E, P0), Pn...)</tt> 73 * is a valid expression. 74 * 75 * @li Otherwise, <tt>boost::asio::prefer(E, P0, Pn...)</tt> is ill-formed. 76 */ 77 inline constexpr unspecified prefer = unspecified; 78 79 /// A type trait that determines whether a @c prefer expression is well-formed. 80 /** 81 * Class template @c can_prefer is a trait that is derived from 82 * @c true_type if the expression <tt>boost::asio::prefer(std::declval<T>(), 83 * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type. 84 */ 85 template <typename T, typename... Properties> 86 struct can_prefer : 87 integral_constant<bool, automatically_determined> 88 { 89 }; 90 91 /// A type trait that determines whether a @c prefer expression will not throw. 92 /** 93 * Class template @c is_nothrow_prefer is a trait that is derived from 94 * @c true_type if the expression <tt>boost::asio::prefer(std::declval<T>(), 95 * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type. 96 */ 97 template <typename T, typename... Properties> 98 struct is_nothrow_prefer : 99 integral_constant<bool, automatically_determined> 100 { 101 }; 102 103 /// A type trait that determines the result type of a @c prefer expression. 104 /** 105 * Class template @c prefer_result is a trait that determines the result 106 * type of the expression <tt>boost::asio::prefer(std::declval<T>(), 107 * std::declval<Properties>()...)</tt>. 108 */ 109 template <typename T, typename... Properties> 110 struct prefer_result 111 { 112 /// The result of the @c prefer expression. 113 typedef automatically_determined type; 114 }; 115 116 } // namespace asio 117 } // namespace boost 118 119 #else // defined(GENERATING_DOCUMENTATION) 120 121 namespace asio_prefer_fn { 122 123 using boost::asio::conditional; 124 using boost::asio::decay; 125 using boost::asio::declval; 126 using boost::asio::enable_if; 127 using boost::asio::is_applicable_property; 128 using boost::asio::traits::prefer_free; 129 using boost::asio::traits::prefer_member; 130 using boost::asio::traits::require_free; 131 using boost::asio::traits::require_member; 132 using boost::asio::traits::static_require; 133 134 void prefer(); 135 void require(); 136 137 enum overload_type 138 { 139 identity, 140 call_require_member, 141 call_require_free, 142 call_prefer_member, 143 call_prefer_free, 144 two_props, 145 n_props, 146 ill_formed 147 }; 148 149 template <typename Impl, typename T, typename Properties, 150 typename = void, typename = void, typename = void, typename = void, 151 typename = void, typename = void, typename = void> 152 struct call_traits 153 { 154 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 155 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 156 typedef void result_type; 157 }; 158 159 template <typename Impl, typename T, typename Property> 160 struct call_traits<Impl, T, void(Property), 161 typename enable_if< 162 is_applicable_property< 163 typename decay<T>::type, 164 typename decay<Property>::type 165 >::value 166 >::type, 167 typename enable_if< 168 decay<Property>::type::is_preferable 169 >::type, 170 typename enable_if< 171 static_require<T, Property>::is_valid 172 >::type> 173 { 174 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); 175 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 176 177 #if defined(BOOST_ASIO_HAS_MOVE) 178 typedef BOOST_ASIO_MOVE_ARG(T) result_type; 179 #else // defined(BOOST_ASIO_HAS_MOVE) 180 typedef BOOST_ASIO_MOVE_ARG(typename decay<T>::type) result_type; 181 #endif // defined(BOOST_ASIO_HAS_MOVE) 182 }; 183 184 template <typename Impl, typename T, typename Property> 185 struct call_traits<Impl, T, void(Property), 186 typename enable_if< 187 is_applicable_property< 188 typename decay<T>::type, 189 typename decay<Property>::type 190 >::value 191 >::type, 192 typename enable_if< 193 decay<Property>::type::is_preferable 194 >::type, 195 typename enable_if< 196 !static_require<T, Property>::is_valid 197 >::type, 198 typename enable_if< 199 require_member<typename Impl::template proxy<T>::type, Property>::is_valid 200 >::type> : 201 require_member<typename Impl::template proxy<T>::type, Property> 202 { 203 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member); 204 }; 205 206 template <typename Impl, typename T, typename Property> 207 struct call_traits<Impl, T, void(Property), 208 typename enable_if< 209 is_applicable_property< 210 typename decay<T>::type, 211 typename decay<Property>::type 212 >::value 213 >::type, 214 typename enable_if< 215 decay<Property>::type::is_preferable 216 >::type, 217 typename enable_if< 218 !static_require<T, Property>::is_valid 219 >::type, 220 typename enable_if< 221 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid 222 >::type, 223 typename enable_if< 224 require_free<T, Property>::is_valid 225 >::type> : 226 require_free<T, Property> 227 { 228 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free); 229 }; 230 231 template <typename Impl, typename T, typename Property> 232 struct call_traits<Impl, T, void(Property), 233 typename enable_if< 234 is_applicable_property< 235 typename decay<T>::type, 236 typename decay<Property>::type 237 >::value 238 >::type, 239 typename enable_if< 240 decay<Property>::type::is_preferable 241 >::type, 242 typename enable_if< 243 !static_require<T, Property>::is_valid 244 >::type, 245 typename enable_if< 246 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid 247 >::type, 248 typename enable_if< 249 !require_free<T, Property>::is_valid 250 >::type, 251 typename enable_if< 252 prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid 253 >::type> : 254 prefer_member<typename Impl::template proxy<T>::type, Property> 255 { 256 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member); 257 }; 258 259 template <typename Impl, typename T, typename Property> 260 struct call_traits<Impl, T, void(Property), 261 typename enable_if< 262 is_applicable_property< 263 typename decay<T>::type, 264 typename decay<Property>::type 265 >::value 266 >::type, 267 typename enable_if< 268 decay<Property>::type::is_preferable 269 >::type, 270 typename enable_if< 271 !static_require<T, Property>::is_valid 272 >::type, 273 typename enable_if< 274 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid 275 >::type, 276 typename enable_if< 277 !require_free<T, Property>::is_valid 278 >::type, 279 typename enable_if< 280 !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid 281 >::type, 282 typename enable_if< 283 prefer_free<T, Property>::is_valid 284 >::type> : 285 prefer_free<T, Property> 286 { 287 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free); 288 }; 289 290 template <typename Impl, typename T, typename Property> 291 struct call_traits<Impl, T, void(Property), 292 typename enable_if< 293 is_applicable_property< 294 typename decay<T>::type, 295 typename decay<Property>::type 296 >::value 297 >::type, 298 typename enable_if< 299 decay<Property>::type::is_preferable 300 >::type, 301 typename enable_if< 302 !static_require<T, Property>::is_valid 303 >::type, 304 typename enable_if< 305 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid 306 >::type, 307 typename enable_if< 308 !require_free<T, Property>::is_valid 309 >::type, 310 typename enable_if< 311 !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid 312 >::type, 313 typename enable_if< 314 !prefer_free<T, Property>::is_valid 315 >::type> 316 { 317 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); 318 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); 319 320 #if defined(BOOST_ASIO_HAS_MOVE) 321 typedef BOOST_ASIO_MOVE_ARG(T) result_type; 322 #else // defined(BOOST_ASIO_HAS_MOVE) 323 typedef BOOST_ASIO_MOVE_ARG(typename decay<T>::type) result_type; 324 #endif // defined(BOOST_ASIO_HAS_MOVE) 325 }; 326 327 template <typename Impl, typename T, typename P0, typename P1> 328 struct call_traits<Impl, T, void(P0, P1), 329 typename enable_if< 330 call_traits<Impl, T, void(P0)>::overload != ill_formed 331 >::type, 332 typename enable_if< 333 call_traits< 334 Impl, 335 typename call_traits<Impl, T, void(P0)>::result_type, 336 void(P1) 337 >::overload != ill_formed 338 >::type> 339 { 340 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props); 341 342 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 343 ( 344 call_traits<Impl, T, void(P0)>::is_noexcept 345 && 346 call_traits< 347 Impl, 348 typename call_traits<Impl, T, void(P0)>::result_type, 349 void(P1) 350 >::is_noexcept 351 )); 352 353 typedef typename decay< 354 typename call_traits< 355 Impl, 356 typename call_traits<Impl, T, void(P0)>::result_type, 357 void(P1) 358 >::result_type 359 >::type result_type; 360 }; 361 362 template <typename Impl, typename T, typename P0, 363 typename P1, typename BOOST_ASIO_ELLIPSIS PN> 364 struct call_traits<Impl, T, void(P0, P1, PN BOOST_ASIO_ELLIPSIS), 365 typename enable_if< 366 call_traits<Impl, T, void(P0)>::overload != ill_formed 367 >::type, 368 typename enable_if< 369 call_traits< 370 Impl, 371 typename call_traits<Impl, T, void(P0)>::result_type, 372 void(P1, PN BOOST_ASIO_ELLIPSIS) 373 >::overload != ill_formed 374 >::type> 375 { 376 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props); 377 378 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = 379 ( 380 call_traits<Impl, T, void(P0)>::is_noexcept 381 && 382 call_traits< 383 Impl, 384 typename call_traits<Impl, T, void(P0)>::result_type, 385 void(P1, PN BOOST_ASIO_ELLIPSIS) 386 >::is_noexcept 387 )); 388 389 typedef typename decay< 390 typename call_traits< 391 Impl, 392 typename call_traits<Impl, T, void(P0)>::result_type, 393 void(P1, PN BOOST_ASIO_ELLIPSIS) 394 >::result_type 395 >::type result_type; 396 }; 397 398 struct impl 399 { 400 template <typename T> 401 struct proxy 402 { 403 #if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \ 404 && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 405 struct type 406 { 407 template <typename P> 408 auto require(BOOST_ASIO_MOVE_ARG(P) p) 409 noexcept( 410 noexcept( 411 declval<typename conditional<true, T, P>::type>().require( 412 BOOST_ASIO_MOVE_CAST(P)(p)) 413 ) 414 ) 415 -> decltype( 416 declval<typename conditional<true, T, P>::type>().require( 417 BOOST_ASIO_MOVE_CAST(P)(p)) 418 ); 419 420 template <typename P> 421 auto prefer(BOOST_ASIO_MOVE_ARG(P) p) 422 noexcept( 423 noexcept( 424 declval<typename conditional<true, T, P>::type>().prefer( 425 BOOST_ASIO_MOVE_CAST(P)(p)) 426 ) 427 ) 428 -> decltype( 429 declval<typename conditional<true, T, P>::type>().prefer( 430 BOOST_ASIO_MOVE_CAST(P)(p)) 431 ); 432 }; 433 #else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 434 // && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 435 typedef T type; 436 #endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 437 // && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) 438 }; 439 440 template <typename T, typename Property> 441 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 442 call_traits<impl, T, void(Property)>::overload == identity, 443 typename call_traits<impl, T, void(Property)>::result_type 444 >::type operator ()asio_prefer_fn::impl445 operator()( 446 BOOST_ASIO_MOVE_ARG(T) t, 447 BOOST_ASIO_MOVE_ARG(Property)) const 448 BOOST_ASIO_NOEXCEPT_IF(( 449 call_traits<impl, T, void(Property)>::is_noexcept)) 450 { 451 return BOOST_ASIO_MOVE_CAST(T)(t); 452 } 453 454 template <typename T, typename Property> 455 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 456 call_traits<impl, T, void(Property)>::overload == call_require_member, 457 typename call_traits<impl, T, void(Property)>::result_type 458 >::type operator ()asio_prefer_fn::impl459 operator()( 460 BOOST_ASIO_MOVE_ARG(T) t, 461 BOOST_ASIO_MOVE_ARG(Property) p) const 462 BOOST_ASIO_NOEXCEPT_IF(( 463 call_traits<impl, T, void(Property)>::is_noexcept)) 464 { 465 return BOOST_ASIO_MOVE_CAST(T)(t).require( 466 BOOST_ASIO_MOVE_CAST(Property)(p)); 467 } 468 469 template <typename T, typename Property> 470 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 471 call_traits<impl, T, void(Property)>::overload == call_require_free, 472 typename call_traits<impl, T, void(Property)>::result_type 473 >::type operator ()asio_prefer_fn::impl474 operator()( 475 BOOST_ASIO_MOVE_ARG(T) t, 476 BOOST_ASIO_MOVE_ARG(Property) p) const 477 BOOST_ASIO_NOEXCEPT_IF(( 478 call_traits<impl, T, void(Property)>::is_noexcept)) 479 { 480 return require( 481 BOOST_ASIO_MOVE_CAST(T)(t), 482 BOOST_ASIO_MOVE_CAST(Property)(p)); 483 } 484 485 template <typename T, typename Property> 486 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 487 call_traits<impl, T, void(Property)>::overload == call_prefer_member, 488 typename call_traits<impl, T, void(Property)>::result_type 489 >::type operator ()asio_prefer_fn::impl490 operator()( 491 BOOST_ASIO_MOVE_ARG(T) t, 492 BOOST_ASIO_MOVE_ARG(Property) p) const 493 BOOST_ASIO_NOEXCEPT_IF(( 494 call_traits<impl, T, void(Property)>::is_noexcept)) 495 { 496 return BOOST_ASIO_MOVE_CAST(T)(t).prefer( 497 BOOST_ASIO_MOVE_CAST(Property)(p)); 498 } 499 500 template <typename T, typename Property> 501 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 502 call_traits<impl, T, void(Property)>::overload == call_prefer_free, 503 typename call_traits<impl, T, void(Property)>::result_type 504 >::type operator ()asio_prefer_fn::impl505 operator()( 506 BOOST_ASIO_MOVE_ARG(T) t, 507 BOOST_ASIO_MOVE_ARG(Property) p) const 508 BOOST_ASIO_NOEXCEPT_IF(( 509 call_traits<impl, T, void(Property)>::is_noexcept)) 510 { 511 return prefer( 512 BOOST_ASIO_MOVE_CAST(T)(t), 513 BOOST_ASIO_MOVE_CAST(Property)(p)); 514 } 515 516 template <typename T, typename P0, typename P1> 517 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 518 call_traits<impl, T, void(P0, P1)>::overload == two_props, 519 typename call_traits<impl, T, void(P0, P1)>::result_type 520 >::type operator ()asio_prefer_fn::impl521 operator()( 522 BOOST_ASIO_MOVE_ARG(T) t, 523 BOOST_ASIO_MOVE_ARG(P0) p0, 524 BOOST_ASIO_MOVE_ARG(P1) p1) const 525 BOOST_ASIO_NOEXCEPT_IF(( 526 call_traits<impl, T, void(P0, P1)>::is_noexcept)) 527 { 528 return (*this)( 529 (*this)( 530 BOOST_ASIO_MOVE_CAST(T)(t), 531 BOOST_ASIO_MOVE_CAST(P0)(p0)), 532 BOOST_ASIO_MOVE_CAST(P1)(p1)); 533 } 534 535 template <typename T, typename P0, typename P1, 536 typename BOOST_ASIO_ELLIPSIS PN> 537 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 538 call_traits<impl, T, 539 void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::overload == n_props, 540 typename call_traits<impl, T, 541 void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::result_type 542 >::type operator ()asio_prefer_fn::impl543 operator()( 544 BOOST_ASIO_MOVE_ARG(T) t, 545 BOOST_ASIO_MOVE_ARG(P0) p0, 546 BOOST_ASIO_MOVE_ARG(P1) p1, 547 BOOST_ASIO_MOVE_ARG(PN) BOOST_ASIO_ELLIPSIS pn) const 548 BOOST_ASIO_NOEXCEPT_IF(( 549 call_traits<impl, T, void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::is_noexcept)) 550 { 551 return (*this)( 552 (*this)( 553 BOOST_ASIO_MOVE_CAST(T)(t), 554 BOOST_ASIO_MOVE_CAST(P0)(p0)), 555 BOOST_ASIO_MOVE_CAST(P1)(p1), 556 BOOST_ASIO_MOVE_CAST(PN)(pn) BOOST_ASIO_ELLIPSIS); 557 } 558 }; 559 560 template <typename T = impl> 561 struct static_instance 562 { 563 static const T instance; 564 }; 565 566 template <typename T> 567 const T static_instance<T>::instance = {}; 568 569 } // namespace asio_prefer_fn 570 namespace boost { 571 namespace asio { 572 namespace { 573 574 static BOOST_ASIO_CONSTEXPR const asio_prefer_fn::impl& 575 prefer = asio_prefer_fn::static_instance<>::instance; 576 577 } // namespace 578 579 typedef asio_prefer_fn::impl prefer_t; 580 581 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 582 583 template <typename T, typename... Properties> 584 struct can_prefer : 585 integral_constant<bool, 586 asio_prefer_fn::call_traits< 587 prefer_t, T, void(Properties...)>::overload 588 != asio_prefer_fn::ill_formed> 589 { 590 }; 591 592 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 593 594 template <typename T, typename P0 = void, 595 typename P1 = void, typename P2 = void> 596 struct can_prefer : 597 integral_constant<bool, 598 asio_prefer_fn::call_traits< 599 prefer_t, T, void(P0, P1, P2)>::overload 600 != asio_prefer_fn::ill_formed> 601 { 602 }; 603 604 template <typename T, typename P0, typename P1> 605 struct can_prefer<T, P0, P1> : 606 integral_constant<bool, 607 asio_prefer_fn::call_traits< 608 prefer_t, T, void(P0, P1)>::overload 609 != asio_prefer_fn::ill_formed> 610 { 611 }; 612 613 template <typename T, typename P0> 614 struct can_prefer<T, P0> : 615 integral_constant<bool, 616 asio_prefer_fn::call_traits< 617 prefer_t, T, void(P0)>::overload 618 != asio_prefer_fn::ill_formed> 619 { 620 }; 621 622 template <typename T> 623 struct can_prefer<T> : 624 false_type 625 { 626 }; 627 628 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 629 630 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 631 632 template <typename T, typename BOOST_ASIO_ELLIPSIS Properties> 633 constexpr bool can_prefer_v 634 = can_prefer<T, Properties BOOST_ASIO_ELLIPSIS>::value; 635 636 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 637 638 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 639 640 template <typename T, typename... Properties> 641 struct is_nothrow_prefer : 642 integral_constant<bool, 643 asio_prefer_fn::call_traits< 644 prefer_t, T, void(Properties...)>::is_noexcept> 645 { 646 }; 647 648 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 649 650 template <typename T, typename P0 = void, 651 typename P1 = void, typename P2 = void> 652 struct is_nothrow_prefer : 653 integral_constant<bool, 654 asio_prefer_fn::call_traits< 655 prefer_t, T, void(P0, P1, P2)>::is_noexcept> 656 { 657 }; 658 659 template <typename T, typename P0, typename P1> 660 struct is_nothrow_prefer<T, P0, P1> : 661 integral_constant<bool, 662 asio_prefer_fn::call_traits< 663 prefer_t, T, void(P0, P1)>::is_noexcept> 664 { 665 }; 666 667 template <typename T, typename P0> 668 struct is_nothrow_prefer<T, P0> : 669 integral_constant<bool, 670 asio_prefer_fn::call_traits< 671 prefer_t, T, void(P0)>::is_noexcept> 672 { 673 }; 674 675 template <typename T> 676 struct is_nothrow_prefer<T> : 677 false_type 678 { 679 }; 680 681 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 682 683 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 684 685 template <typename T, typename BOOST_ASIO_ELLIPSIS Properties> 686 constexpr bool is_nothrow_prefer_v 687 = is_nothrow_prefer<T, Properties BOOST_ASIO_ELLIPSIS>::value; 688 689 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 690 691 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 692 693 template <typename T, typename... Properties> 694 struct prefer_result 695 { 696 typedef typename asio_prefer_fn::call_traits< 697 prefer_t, T, void(Properties...)>::result_type type; 698 }; 699 700 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 701 702 template <typename T, typename P0 = void, 703 typename P1 = void, typename P2 = void> 704 struct prefer_result 705 { 706 typedef typename asio_prefer_fn::call_traits< 707 prefer_t, T, void(P0, P1, P2)>::result_type type; 708 }; 709 710 template <typename T, typename P0, typename P1> 711 struct prefer_result<T, P0, P1> 712 { 713 typedef typename asio_prefer_fn::call_traits< 714 prefer_t, T, void(P0, P1)>::result_type type; 715 }; 716 717 template <typename T, typename P0> 718 struct prefer_result<T, P0> 719 { 720 typedef typename asio_prefer_fn::call_traits< 721 prefer_t, T, void(P0)>::result_type type; 722 }; 723 724 template <typename T> 725 struct prefer_result<T> 726 { 727 }; 728 729 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 730 731 } // namespace asio 732 } // namespace boost 733 734 #endif // defined(GENERATING_DOCUMENTATION) 735 736 #include <boost/asio/detail/pop_options.hpp> 737 738 #endif // BOOST_ASIO_PREFER_HPP 739