1 // 2 // execution/set_value.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_SET_VALUE_HPP 12 #define BOOST_ASIO_EXECUTION_SET_VALUE_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/detail/variadic_templates.hpp> 21 #include <boost/asio/traits/set_value_member.hpp> 22 #include <boost/asio/traits/set_value_free.hpp> 23 24 #include <boost/asio/detail/push_options.hpp> 25 26 #if defined(GENERATING_DOCUMENTATION) 27 28 namespace boost { 29 namespace asio { 30 namespace execution { 31 32 /// A customisation point that delivers a value to a receiver. 33 /** 34 * The name <tt>execution::set_value</tt> denotes a customisation point object. 35 * The expression <tt>execution::set_value(R, Vs...)</tt> for some 36 * subexpressions <tt>R</tt> and <tt>Vs...</tt> is expression-equivalent to: 37 * 38 * @li <tt>R.set_value(Vs...)</tt>, if that expression is valid. If the 39 * function selected does not send the value(s) <tt>Vs...</tt> to the receiver 40 * <tt>R</tt>'s value channel, the program is ill-formed with no diagnostic 41 * required. 42 * 43 * @li Otherwise, <tt>set_value(R, Vs...)</tt>, if that expression is valid, 44 * with overload resolution performed in a context that includes the 45 * declaration <tt>void set_value();</tt> and that does not include a 46 * declaration of <tt>execution::set_value</tt>. If the function selected by 47 * overload resolution does not send the value(s) <tt>Vs...</tt> to the 48 * receiver <tt>R</tt>'s value channel, the program is ill-formed with no 49 * diagnostic required. 50 * 51 * @li Otherwise, <tt>execution::set_value(R, Vs...)</tt> is ill-formed. 52 */ 53 inline constexpr unspecified set_value = unspecified; 54 55 /// A type trait that determines whether a @c set_value expression is 56 /// well-formed. 57 /** 58 * Class template @c can_set_value is a trait that is derived from 59 * @c true_type if the expression <tt>execution::set_value(std::declval<R>(), 60 * std::declval<Vs>()...)</tt> is well formed; otherwise @c false_type. 61 */ 62 template <typename R, typename... Vs> 63 struct can_set_value : 64 integral_constant<bool, automatically_determined> 65 { 66 }; 67 68 } // namespace execution 69 } // namespace asio 70 } // namespace boost 71 72 #else // defined(GENERATING_DOCUMENTATION) 73 74 namespace asio_execution_set_value_fn { 75 76 using boost::asio::decay; 77 using boost::asio::declval; 78 using boost::asio::enable_if; 79 using boost::asio::traits::set_value_free; 80 using boost::asio::traits::set_value_member; 81 82 void set_value(); 83 84 enum overload_type 85 { 86 call_member, 87 call_free, 88 ill_formed 89 }; 90 91 template <typename R, typename Vs, typename = void> 92 struct call_traits 93 { 94 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 95 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 96 typedef void result_type; 97 }; 98 99 template <typename R, typename Vs> 100 struct call_traits<R, Vs, 101 typename enable_if< 102 ( 103 set_value_member<R, Vs>::is_valid 104 ) 105 >::type> : 106 set_value_member<R, Vs> 107 { 108 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 109 }; 110 111 template <typename R, typename Vs> 112 struct call_traits<R, Vs, 113 typename enable_if< 114 ( 115 !set_value_member<R, Vs>::is_valid 116 && 117 set_value_free<R, Vs>::is_valid 118 ) 119 >::type> : 120 set_value_free<R, Vs> 121 { 122 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 123 }; 124 125 struct impl 126 { 127 #if defined(BOOST_ASIO_HAS_MOVE) 128 129 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 130 131 template <typename R, typename... Vs> 132 BOOST_ASIO_CONSTEXPR typename enable_if< 133 call_traits<R, void(Vs...)>::overload == call_member, 134 typename call_traits<R, void(Vs...)>::result_type 135 >::type operator ()asio_execution_set_value_fn::impl136 operator()(R&& r, Vs&&... v) const 137 BOOST_ASIO_NOEXCEPT_IF(( 138 call_traits<R, void(Vs...)>::is_noexcept)) 139 { 140 return BOOST_ASIO_MOVE_CAST(R)(r).set_value(BOOST_ASIO_MOVE_CAST(Vs)(v)...); 141 } 142 143 template <typename R, typename... Vs> 144 BOOST_ASIO_CONSTEXPR typename enable_if< 145 call_traits<R, void(Vs...)>::overload == call_free, 146 typename call_traits<R, void(Vs...)>::result_type 147 >::type operator ()asio_execution_set_value_fn::impl148 operator()(R&& r, Vs&&... v) const 149 BOOST_ASIO_NOEXCEPT_IF(( 150 call_traits<R, void(Vs...)>::is_noexcept)) 151 { 152 return set_value(BOOST_ASIO_MOVE_CAST(R)(r), 153 BOOST_ASIO_MOVE_CAST(Vs)(v)...); 154 } 155 156 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 157 158 template <typename R> 159 BOOST_ASIO_CONSTEXPR typename enable_if< 160 call_traits<R, void()>::overload == call_member, 161 typename call_traits<R, void()>::result_type 162 >::type 163 operator()(R&& r) const 164 BOOST_ASIO_NOEXCEPT_IF(( 165 call_traits<R, void()>::is_noexcept)) 166 { 167 return BOOST_ASIO_MOVE_CAST(R)(r).set_value(); 168 } 169 170 template <typename R> 171 BOOST_ASIO_CONSTEXPR typename enable_if< 172 call_traits<R, void()>::overload == call_free, 173 typename call_traits<R, void()>::result_type 174 >::type 175 operator()(R&& r) const 176 BOOST_ASIO_NOEXCEPT_IF(( 177 call_traits<R, void()>::is_noexcept)) 178 { 179 return set_value(BOOST_ASIO_MOVE_CAST(R)(r)); 180 } 181 182 #define BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ 183 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 184 BOOST_ASIO_CONSTEXPR typename enable_if< \ 185 call_traits<R, \ 186 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 187 typename call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 188 >::type \ 189 operator()(R&& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 190 BOOST_ASIO_NOEXCEPT_IF(( \ 191 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 192 { \ 193 return BOOST_ASIO_MOVE_CAST(R)(r).set_value( \ 194 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 195 } \ 196 \ 197 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 198 BOOST_ASIO_CONSTEXPR typename enable_if< \ 199 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 200 typename call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 201 >::type \ 202 operator()(R&& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 203 BOOST_ASIO_NOEXCEPT_IF(( \ 204 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 205 { \ 206 return set_value(BOOST_ASIO_MOVE_CAST(R)(r), \ 207 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 208 } \ 209 /**/ 210 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF) 211 #undef BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF 212 213 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 214 215 #else // defined(BOOST_ASIO_HAS_MOVE) 216 217 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 218 219 template <typename R, typename... Vs> 220 BOOST_ASIO_CONSTEXPR typename enable_if< 221 call_traits<R&, void(const Vs&...)>::overload == call_member, 222 typename call_traits<R&, void(const Vs&...)>::result_type 223 >::type 224 operator()(R& r, const Vs&... v) const 225 BOOST_ASIO_NOEXCEPT_IF(( 226 call_traits<R&, void(const Vs&...)>::is_noexcept)) 227 { 228 return r.set_value(v...); 229 } 230 231 template <typename R, typename... Vs> 232 BOOST_ASIO_CONSTEXPR typename enable_if< 233 call_traits<const R&, void(const Vs&...)>::overload == call_member, 234 typename call_traits<const R&, void(const Vs&...)>::result_type 235 >::type 236 operator()(const R& r, const Vs&... v) const 237 BOOST_ASIO_NOEXCEPT_IF(( 238 call_traits<const R&, void(const Vs&...)>::is_noexcept)) 239 { 240 return r.set_value(v...); 241 } 242 243 template <typename R, typename... Vs> 244 BOOST_ASIO_CONSTEXPR typename enable_if< 245 call_traits<R&, void(const Vs&...)>::overload == call_free, 246 typename call_traits<R&, void(const Vs&...)>::result_type 247 >::type 248 operator()(R& r, const Vs&... v) const 249 BOOST_ASIO_NOEXCEPT_IF(( 250 call_traits<R&, void(const Vs&...)>::is_noexcept)) 251 { 252 return set_value(r, v...); 253 } 254 255 template <typename R, typename... Vs> 256 BOOST_ASIO_CONSTEXPR typename enable_if< 257 call_traits<const R&, void(const Vs&...)>::overload == call_free, 258 typename call_traits<const R&, void(const Vs&...)>::result_type 259 >::type 260 operator()(const R& r, const Vs&... v) const 261 BOOST_ASIO_NOEXCEPT_IF(( 262 call_traits<const R&, void(const Vs&...)>::is_noexcept)) 263 { 264 return set_value(r, v...); 265 } 266 267 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 268 269 template <typename R> 270 BOOST_ASIO_CONSTEXPR typename enable_if< 271 call_traits<R&, void()>::overload == call_member, 272 typename call_traits<R&, void()>::result_type 273 >::type 274 operator()(R& r) const 275 BOOST_ASIO_NOEXCEPT_IF(( 276 call_traits<R&, void()>::is_noexcept)) 277 { 278 return r.set_value(); 279 } 280 281 template <typename R> 282 BOOST_ASIO_CONSTEXPR typename enable_if< 283 call_traits<const R&, void()>::overload == call_member, 284 typename call_traits<const R&, void()>::result_type 285 >::type 286 operator()(const R& r) const 287 BOOST_ASIO_NOEXCEPT_IF(( 288 call_traits<const R&, void()>::is_noexcept)) 289 { 290 return r.set_value(); 291 } 292 293 template <typename R> 294 BOOST_ASIO_CONSTEXPR typename enable_if< 295 call_traits<R&, void()>::overload == call_free, 296 typename call_traits<R&, void()>::result_type 297 >::type 298 operator()(R& r) const 299 BOOST_ASIO_NOEXCEPT_IF(( 300 call_traits<R&, void()>::is_noexcept)) 301 { 302 return set_value(r); 303 } 304 305 template <typename R> 306 BOOST_ASIO_CONSTEXPR typename enable_if< 307 call_traits<const R&, void()>::overload == call_free, 308 typename call_traits<const R&, void()>::result_type 309 >::type 310 operator()(const R& r) const 311 BOOST_ASIO_NOEXCEPT_IF(( 312 call_traits<const R&, void()>::is_noexcept)) 313 { 314 return set_value(r); 315 } 316 317 #define BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ 318 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 319 BOOST_ASIO_CONSTEXPR typename enable_if< \ 320 call_traits<R&, \ 321 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 322 typename call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 323 >::type \ 324 operator()(R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 325 BOOST_ASIO_NOEXCEPT_IF(( \ 326 call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 327 { \ 328 return r.set_value(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 329 } \ 330 \ 331 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 332 BOOST_ASIO_CONSTEXPR typename enable_if< \ 333 call_traits<const R&, \ 334 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 335 typename call_traits<const R&, \ 336 void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 337 >::type \ 338 operator()(const R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 339 BOOST_ASIO_NOEXCEPT_IF(( \ 340 call_traits<const R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 341 { \ 342 return r.set_value(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 343 } \ 344 \ 345 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 346 BOOST_ASIO_CONSTEXPR typename enable_if< \ 347 call_traits<R&, \ 348 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 349 typename call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 350 >::type \ 351 operator()(R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 352 BOOST_ASIO_NOEXCEPT_IF(( \ 353 call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 354 { \ 355 return set_value(r, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 356 } \ 357 \ 358 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 359 BOOST_ASIO_CONSTEXPR typename enable_if< \ 360 call_traits<const R&, \ 361 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 362 typename call_traits<const R&, \ 363 void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 364 >::type \ 365 operator()(const R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 366 BOOST_ASIO_NOEXCEPT_IF(( \ 367 call_traits<const R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 368 { \ 369 return set_value(r, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 370 } \ 371 /**/ 372 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF) 373 #undef BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF 374 375 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 376 377 #endif // defined(BOOST_ASIO_HAS_MOVE) 378 }; 379 380 template <typename T = impl> 381 struct static_instance 382 { 383 static const T instance; 384 }; 385 386 template <typename T> 387 const T static_instance<T>::instance = {}; 388 389 } // namespace asio_execution_set_value_fn 390 namespace boost { 391 namespace asio { 392 namespace execution { 393 namespace { 394 395 static BOOST_ASIO_CONSTEXPR const asio_execution_set_value_fn::impl& 396 set_value = asio_execution_set_value_fn::static_instance<>::instance; 397 398 } // namespace 399 400 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 401 402 template <typename R, typename... Vs> 403 struct can_set_value : 404 integral_constant<bool, 405 asio_execution_set_value_fn::call_traits<R, void(Vs...)>::overload != 406 asio_execution_set_value_fn::ill_formed> 407 { 408 }; 409 410 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 411 412 template <typename R, typename... Vs> 413 constexpr bool can_set_value_v = can_set_value<R, Vs...>::value; 414 415 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 416 417 template <typename R, typename... Vs> 418 struct is_nothrow_set_value : 419 integral_constant<bool, 420 asio_execution_set_value_fn::call_traits<R, void(Vs...)>::is_noexcept> 421 { 422 }; 423 424 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 425 426 template <typename R, typename... Vs> 427 constexpr bool is_nothrow_set_value_v 428 = is_nothrow_set_value<R, Vs...>::value; 429 430 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 431 432 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 433 434 template <typename R, typename = void, 435 typename = void, typename = void, typename = void, typename = void, 436 typename = void, typename = void, typename = void, typename = void> 437 struct can_set_value; 438 439 template <typename R, typename = void, 440 typename = void, typename = void, typename = void, typename = void, 441 typename = void, typename = void, typename = void, typename = void> 442 struct is_nothrow_set_value; 443 444 template <typename R> 445 struct can_set_value<R> : 446 integral_constant<bool, 447 asio_execution_set_value_fn::call_traits<R, void()>::overload != 448 asio_execution_set_value_fn::ill_formed> 449 { 450 }; 451 452 template <typename R> 453 struct is_nothrow_set_value<R> : 454 integral_constant<bool, 455 asio_execution_set_value_fn::call_traits<R, void()>::is_noexcept> 456 { 457 }; 458 459 #define BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF(n) \ 460 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 461 struct can_set_value<R, BOOST_ASIO_VARIADIC_TARGS(n)> : \ 462 integral_constant<bool, \ 463 asio_execution_set_value_fn::call_traits<R, \ 464 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload != \ 465 asio_execution_set_value_fn::ill_formed> \ 466 { \ 467 }; \ 468 \ 469 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 470 struct is_nothrow_set_value<R, BOOST_ASIO_VARIADIC_TARGS(n)> : \ 471 integral_constant<bool, \ 472 asio_execution_set_value_fn::call_traits<R, \ 473 void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept> \ 474 { \ 475 }; \ 476 /**/ 477 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF) 478 #undef BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF 479 480 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 481 482 } // namespace execution 483 } // namespace asio 484 } // namespace boost 485 486 #endif // defined(GENERATING_DOCUMENTATION) 487 488 #include <boost/asio/detail/pop_options.hpp> 489 490 #endif // BOOST_ASIO_EXECUTION_SET_VALUE_HPP 491