as_single.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //
  2. // experimental/impl/as_single.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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. #ifndef ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP
  11. #define ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include <tuple>
  17. #include "asio/associator.hpp"
  18. #include "asio/async_result.hpp"
  19. #include "asio/detail/handler_cont_helpers.hpp"
  20. #include "asio/detail/type_traits.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. namespace asio {
  23. namespace experimental {
  24. namespace detail {
  25. // Class to adapt a as_single_t as a completion handler.
  26. template <typename Handler>
  27. class as_single_handler
  28. {
  29. public:
  30. typedef void result_type;
  31. template <typename CompletionToken>
  32. as_single_handler(as_single_t<CompletionToken> e)
  33. : handler_(static_cast<CompletionToken&&>(e.token_))
  34. {
  35. }
  36. template <typename RedirectedHandler>
  37. as_single_handler(RedirectedHandler&& h)
  38. : handler_(static_cast<RedirectedHandler&&>(h))
  39. {
  40. }
  41. void operator()()
  42. {
  43. static_cast<Handler&&>(handler_)();
  44. }
  45. template <typename Arg>
  46. void operator()(Arg&& arg)
  47. {
  48. static_cast<Handler&&>(handler_)(static_cast<Arg&&>(arg));
  49. }
  50. template <typename... Args>
  51. void operator()(Args&&... args)
  52. {
  53. static_cast<Handler&&>(handler_)(
  54. std::make_tuple(static_cast<Args&&>(args)...));
  55. }
  56. //private:
  57. Handler handler_;
  58. };
  59. template <typename Handler>
  60. inline bool asio_handler_is_continuation(
  61. as_single_handler<Handler>* this_handler)
  62. {
  63. return asio_handler_cont_helpers::is_continuation(
  64. this_handler->handler_);
  65. }
  66. template <typename Signature>
  67. struct as_single_signature
  68. {
  69. typedef Signature type;
  70. };
  71. template <typename R>
  72. struct as_single_signature<R()>
  73. {
  74. typedef R type();
  75. };
  76. template <typename R, typename Arg>
  77. struct as_single_signature<R(Arg)>
  78. {
  79. typedef R type(Arg);
  80. };
  81. template <typename R, typename... Args>
  82. struct as_single_signature<R(Args...)>
  83. {
  84. typedef R type(std::tuple<decay_t<Args>...>);
  85. };
  86. } // namespace detail
  87. } // namespace experimental
  88. #if !defined(GENERATING_DOCUMENTATION)
  89. template <typename CompletionToken, typename Signature>
  90. struct async_result<experimental::as_single_t<CompletionToken>, Signature>
  91. {
  92. template <typename Initiation>
  93. struct init_wrapper
  94. {
  95. init_wrapper(Initiation init)
  96. : initiation_(static_cast<Initiation&&>(init))
  97. {
  98. }
  99. template <typename Handler, typename... Args>
  100. void operator()(Handler&& handler, Args&&... args)
  101. {
  102. static_cast<Initiation&&>(initiation_)(
  103. experimental::detail::as_single_handler<decay_t<Handler>>(
  104. static_cast<Handler&&>(handler)),
  105. static_cast<Args&&>(args)...);
  106. }
  107. Initiation initiation_;
  108. };
  109. template <typename Initiation, typename RawCompletionToken, typename... Args>
  110. static auto initiate(Initiation&& initiation,
  111. RawCompletionToken&& token, Args&&... args)
  112. -> decltype(
  113. async_initiate<CompletionToken,
  114. typename experimental::detail::as_single_signature<Signature>::type>(
  115. init_wrapper<decay_t<Initiation>>(
  116. static_cast<Initiation&&>(initiation)),
  117. token.token_, static_cast<Args&&>(args)...))
  118. {
  119. return async_initiate<CompletionToken,
  120. typename experimental::detail::as_single_signature<Signature>::type>(
  121. init_wrapper<decay_t<Initiation>>(
  122. static_cast<Initiation&&>(initiation)),
  123. token.token_, static_cast<Args&&>(args)...);
  124. }
  125. };
  126. template <template <typename, typename> class Associator,
  127. typename Handler, typename DefaultCandidate>
  128. struct associator<Associator,
  129. experimental::detail::as_single_handler<Handler>, DefaultCandidate>
  130. : Associator<Handler, DefaultCandidate>
  131. {
  132. static typename Associator<Handler, DefaultCandidate>::type get(
  133. const experimental::detail::as_single_handler<Handler>& h) noexcept
  134. {
  135. return Associator<Handler, DefaultCandidate>::get(h.handler_);
  136. }
  137. static auto get(const experimental::detail::as_single_handler<Handler>& h,
  138. const DefaultCandidate& c) noexcept
  139. -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c))
  140. {
  141. return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
  142. }
  143. };
  144. #endif // !defined(GENERATING_DOCUMENTATION)
  145. } // namespace asio
  146. #include "asio/detail/pop_options.hpp"
  147. #endif // ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP