1 // 2 // execution/set_value.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_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, 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 set_value_member<R, Vs>::is_valid 103 >::type> : 104 set_value_member<R, Vs> 105 { 106 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 107 }; 108 109 template <typename R, typename Vs> 110 struct call_traits<R, Vs, 111 typename enable_if< 112 !set_value_member<R, Vs>::is_valid 113 >::type, 114 typename enable_if< 115 set_value_free<R, Vs>::is_valid 116 >::type> : 117 set_value_free<R, Vs> 118 { 119 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 120 }; 121 122 struct impl 123 { 124 #if defined(BOOST_ASIO_HAS_MOVE) 125 126 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 127 128 template <typename R, typename... Vs> 129 BOOST_ASIO_CONSTEXPR typename enable_if< 130 call_traits<R, void(Vs...)>::overload == call_member, 131 typename call_traits<R, void(Vs...)>::result_type 132 >::type operator ()asio_execution_set_value_fn::impl133 operator()(R&& r, Vs&&... v) const 134 BOOST_ASIO_NOEXCEPT_IF(( 135 call_traits<R, void(Vs...)>::is_noexcept)) 136 { 137 return BOOST_ASIO_MOVE_CAST(R)(r).set_value(BOOST_ASIO_MOVE_CAST(Vs)(v)...); 138 } 139 140 template <typename R, typename... Vs> 141 BOOST_ASIO_CONSTEXPR typename enable_if< 142 call_traits<R, void(Vs...)>::overload == call_free, 143 typename call_traits<R, void(Vs...)>::result_type 144 >::type operator ()asio_execution_set_value_fn::impl145 operator()(R&& r, Vs&&... v) const 146 BOOST_ASIO_NOEXCEPT_IF(( 147 call_traits<R, void(Vs...)>::is_noexcept)) 148 { 149 return set_value(BOOST_ASIO_MOVE_CAST(R)(r), 150 BOOST_ASIO_MOVE_CAST(Vs)(v)...); 151 } 152 153 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 154 155 template <typename R> 156 BOOST_ASIO_CONSTEXPR typename enable_if< 157 call_traits<R, void()>::overload == call_member, 158 typename call_traits<R, void()>::result_type 159 >::type 160 operator()(R&& r) const 161 BOOST_ASIO_NOEXCEPT_IF(( 162 call_traits<R, void()>::is_noexcept)) 163 { 164 return BOOST_ASIO_MOVE_CAST(R)(r).set_value(); 165 } 166 167 template <typename R> 168 BOOST_ASIO_CONSTEXPR typename enable_if< 169 call_traits<R, void()>::overload == call_free, 170 typename call_traits<R, void()>::result_type 171 >::type 172 operator()(R&& r) const 173 BOOST_ASIO_NOEXCEPT_IF(( 174 call_traits<R, void()>::is_noexcept)) 175 { 176 return set_value(BOOST_ASIO_MOVE_CAST(R)(r)); 177 } 178 179 #define BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ 180 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 181 BOOST_ASIO_CONSTEXPR typename enable_if< \ 182 call_traits<R, \ 183 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 184 typename call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 185 >::type \ 186 operator()(R&& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 187 BOOST_ASIO_NOEXCEPT_IF(( \ 188 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 189 { \ 190 return BOOST_ASIO_MOVE_CAST(R)(r).set_value( \ 191 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 192 } \ 193 \ 194 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 195 BOOST_ASIO_CONSTEXPR typename enable_if< \ 196 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 197 typename call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 198 >::type \ 199 operator()(R&& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 200 BOOST_ASIO_NOEXCEPT_IF(( \ 201 call_traits<R, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 202 { \ 203 return set_value(BOOST_ASIO_MOVE_CAST(R)(r), \ 204 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 205 } \ 206 /**/ 207 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF) 208 #undef BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF 209 210 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 211 212 #else // defined(BOOST_ASIO_HAS_MOVE) 213 214 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 215 216 template <typename R, typename... Vs> 217 BOOST_ASIO_CONSTEXPR typename enable_if< 218 call_traits<R&, void(const Vs&...)>::overload == call_member, 219 typename call_traits<R&, void(const Vs&...)>::result_type 220 >::type 221 operator()(R& r, const Vs&... v) const 222 BOOST_ASIO_NOEXCEPT_IF(( 223 call_traits<R&, void(const Vs&...)>::is_noexcept)) 224 { 225 return r.set_value(v...); 226 } 227 228 template <typename R, typename... Vs> 229 BOOST_ASIO_CONSTEXPR typename enable_if< 230 call_traits<const R&, void(const Vs&...)>::overload == call_member, 231 typename call_traits<const R&, void(const Vs&...)>::result_type 232 >::type 233 operator()(const R& r, const Vs&... v) const 234 BOOST_ASIO_NOEXCEPT_IF(( 235 call_traits<const R&, void(const Vs&...)>::is_noexcept)) 236 { 237 return r.set_value(v...); 238 } 239 240 template <typename R, typename... Vs> 241 BOOST_ASIO_CONSTEXPR typename enable_if< 242 call_traits<R&, void(const Vs&...)>::overload == call_free, 243 typename call_traits<R&, void(const Vs&...)>::result_type 244 >::type 245 operator()(R& r, const Vs&... v) const 246 BOOST_ASIO_NOEXCEPT_IF(( 247 call_traits<R&, void(const Vs&...)>::is_noexcept)) 248 { 249 return set_value(r, v...); 250 } 251 252 template <typename R, typename... Vs> 253 BOOST_ASIO_CONSTEXPR typename enable_if< 254 call_traits<const R&, void(const Vs&...)>::overload == call_free, 255 typename call_traits<const R&, void(const Vs&...)>::result_type 256 >::type 257 operator()(const R& r, const Vs&... v) const 258 BOOST_ASIO_NOEXCEPT_IF(( 259 call_traits<const R&, void(const Vs&...)>::is_noexcept)) 260 { 261 return set_value(r, v...); 262 } 263 264 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 265 266 template <typename R> 267 BOOST_ASIO_CONSTEXPR typename enable_if< 268 call_traits<R&, void()>::overload == call_member, 269 typename call_traits<R&, void()>::result_type 270 >::type 271 operator()(R& r) const 272 BOOST_ASIO_NOEXCEPT_IF(( 273 call_traits<R&, void()>::is_noexcept)) 274 { 275 return r.set_value(); 276 } 277 278 template <typename R> 279 BOOST_ASIO_CONSTEXPR typename enable_if< 280 call_traits<const R&, void()>::overload == call_member, 281 typename call_traits<const R&, void()>::result_type 282 >::type 283 operator()(const R& r) const 284 BOOST_ASIO_NOEXCEPT_IF(( 285 call_traits<const R&, void()>::is_noexcept)) 286 { 287 return r.set_value(); 288 } 289 290 template <typename R> 291 BOOST_ASIO_CONSTEXPR typename enable_if< 292 call_traits<R&, void()>::overload == call_free, 293 typename call_traits<R&, void()>::result_type 294 >::type 295 operator()(R& r) const 296 BOOST_ASIO_NOEXCEPT_IF(( 297 call_traits<R&, void()>::is_noexcept)) 298 { 299 return set_value(r); 300 } 301 302 template <typename R> 303 BOOST_ASIO_CONSTEXPR typename enable_if< 304 call_traits<const R&, void()>::overload == call_free, 305 typename call_traits<const R&, void()>::result_type 306 >::type 307 operator()(const R& r) const 308 BOOST_ASIO_NOEXCEPT_IF(( 309 call_traits<const R&, void()>::is_noexcept)) 310 { 311 return set_value(r); 312 } 313 314 #define BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ 315 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 316 BOOST_ASIO_CONSTEXPR typename enable_if< \ 317 call_traits<R&, \ 318 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 319 typename call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 320 >::type \ 321 operator()(R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 322 BOOST_ASIO_NOEXCEPT_IF(( \ 323 call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 324 { \ 325 return r.set_value(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 326 } \ 327 \ 328 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 329 BOOST_ASIO_CONSTEXPR typename enable_if< \ 330 call_traits<const R&, \ 331 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ 332 typename call_traits<const R&, \ 333 void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 334 >::type \ 335 operator()(const R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 336 BOOST_ASIO_NOEXCEPT_IF(( \ 337 call_traits<const R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 338 { \ 339 return r.set_value(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 340 } \ 341 \ 342 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 343 BOOST_ASIO_CONSTEXPR typename enable_if< \ 344 call_traits<R&, \ 345 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 346 typename call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 347 >::type \ 348 operator()(R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 349 BOOST_ASIO_NOEXCEPT_IF(( \ 350 call_traits<R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 351 { \ 352 return set_value(r, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 353 } \ 354 \ 355 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 356 BOOST_ASIO_CONSTEXPR typename enable_if< \ 357 call_traits<const R&, \ 358 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ 359 typename call_traits<const R&, \ 360 void(BOOST_ASIO_VARIADIC_TARGS(n))>::result_type \ 361 >::type \ 362 operator()(const R& r, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \ 363 BOOST_ASIO_NOEXCEPT_IF(( \ 364 call_traits<const R&, void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ 365 { \ 366 return set_value(r, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \ 367 } \ 368 /**/ 369 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF) 370 #undef BOOST_ASIO_PRIVATE_SET_VALUE_CALL_DEF 371 372 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 373 374 #endif // defined(BOOST_ASIO_HAS_MOVE) 375 }; 376 377 template <typename T = impl> 378 struct static_instance 379 { 380 static const T instance; 381 }; 382 383 template <typename T> 384 const T static_instance<T>::instance = {}; 385 386 } // namespace asio_execution_set_value_fn 387 namespace boost { 388 namespace asio { 389 namespace execution { 390 namespace { 391 392 static BOOST_ASIO_CONSTEXPR const asio_execution_set_value_fn::impl& 393 set_value = asio_execution_set_value_fn::static_instance<>::instance; 394 395 } // namespace 396 397 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 398 399 template <typename R, typename... Vs> 400 struct can_set_value : 401 integral_constant<bool, 402 asio_execution_set_value_fn::call_traits<R, void(Vs...)>::overload != 403 asio_execution_set_value_fn::ill_formed> 404 { 405 }; 406 407 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 408 409 template <typename R, typename... Vs> 410 constexpr bool can_set_value_v = can_set_value<R, Vs...>::value; 411 412 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 413 414 template <typename R, typename... Vs> 415 struct is_nothrow_set_value : 416 integral_constant<bool, 417 asio_execution_set_value_fn::call_traits<R, void(Vs...)>::is_noexcept> 418 { 419 }; 420 421 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 422 423 template <typename R, typename... Vs> 424 constexpr bool is_nothrow_set_value_v 425 = is_nothrow_set_value<R, Vs...>::value; 426 427 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 428 429 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 430 431 template <typename R, typename = void, 432 typename = void, typename = void, typename = void, typename = void, 433 typename = void, typename = void, typename = void, typename = void> 434 struct can_set_value; 435 436 template <typename R, typename = void, 437 typename = void, typename = void, typename = void, typename = void, 438 typename = void, typename = void, typename = void, typename = void> 439 struct is_nothrow_set_value; 440 441 template <typename R> 442 struct can_set_value<R> : 443 integral_constant<bool, 444 asio_execution_set_value_fn::call_traits<R, void()>::overload != 445 asio_execution_set_value_fn::ill_formed> 446 { 447 }; 448 449 template <typename R> 450 struct is_nothrow_set_value<R> : 451 integral_constant<bool, 452 asio_execution_set_value_fn::call_traits<R, void()>::is_noexcept> 453 { 454 }; 455 456 #define BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF(n) \ 457 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 458 struct can_set_value<R, BOOST_ASIO_VARIADIC_TARGS(n)> : \ 459 integral_constant<bool, \ 460 asio_execution_set_value_fn::call_traits<R, \ 461 void(BOOST_ASIO_VARIADIC_TARGS(n))>::overload != \ 462 asio_execution_set_value_fn::ill_formed> \ 463 { \ 464 }; \ 465 \ 466 template <typename R, BOOST_ASIO_VARIADIC_TPARAMS(n)> \ 467 struct is_nothrow_set_value<R, BOOST_ASIO_VARIADIC_TARGS(n)> : \ 468 integral_constant<bool, \ 469 asio_execution_set_value_fn::call_traits<R, \ 470 void(BOOST_ASIO_VARIADIC_TARGS(n))>::is_noexcept> \ 471 { \ 472 }; \ 473 /**/ 474 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF) 475 #undef BOOST_ASIO_PRIVATE_SET_VALUE_TRAITS_DEF 476 477 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) 478 479 } // namespace execution 480 } // namespace asio 481 } // namespace boost 482 483 #endif // defined(GENERATING_DOCUMENTATION) 484 485 #include <boost/asio/detail/pop_options.hpp> 486 487 #endif // BOOST_ASIO_EXECUTION_SET_VALUE_HPP 488