set_error.hpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // execution/set_error.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. #ifndef BOOST_ASIO_EXECUTION_SET_ERROR_HPP
  11. #define BOOST_ASIO_EXECUTION_SET_ERROR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/type_traits.hpp>
  17. #include <boost/asio/traits/set_error_member.hpp>
  18. #include <boost/asio/traits/set_error_free.hpp>
  19. #include <boost/asio/detail/push_options.hpp>
  20. #if defined(GENERATING_DOCUMENTATION)
  21. namespace boost {
  22. namespace asio {
  23. namespace execution {
  24. /// A customisation point that delivers an error notification to a receiver.
  25. /**
  26. * The name <tt>execution::set_error</tt> denotes a customisation point object.
  27. * The expression <tt>execution::set_error(R, E)</tt> for some subexpressions
  28. * <tt>R</tt> and <tt>E</tt> are expression-equivalent to:
  29. *
  30. * @li <tt>R.set_error(E)</tt>, if that expression is valid. If the function
  31. * selected does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s
  32. * error channel, the program is ill-formed with no diagnostic required.
  33. *
  34. * @li Otherwise, <tt>set_error(R, E)</tt>, if that expression is valid, with
  35. * overload resolution performed in a context that includes the declaration
  36. * <tt>void set_error();</tt> and that does not include a declaration of
  37. * <tt>execution::set_error</tt>. If the function selected by overload
  38. * resolution does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s
  39. * error channel, the program is ill-formed with no diagnostic required.
  40. *
  41. * @li Otherwise, <tt>execution::set_error(R, E)</tt> is ill-formed.
  42. */
  43. inline constexpr unspecified set_error = unspecified;
  44. /// A type trait that determines whether a @c set_error expression is
  45. /// well-formed.
  46. /**
  47. * Class template @c can_set_error is a trait that is derived from
  48. * @c true_type if the expression <tt>execution::set_error(std::declval<R>(),
  49. * std::declval<E>())</tt> is well formed; otherwise @c false_type.
  50. */
  51. template <typename R, typename E>
  52. struct can_set_error :
  53. integral_constant<bool, automatically_determined>
  54. {
  55. };
  56. } // namespace execution
  57. } // namespace asio
  58. } // namespace boost
  59. #else // defined(GENERATING_DOCUMENTATION)
  60. namespace asio_execution_set_error_fn {
  61. using boost::asio::decay;
  62. using boost::asio::declval;
  63. using boost::asio::enable_if;
  64. using boost::asio::traits::set_error_free;
  65. using boost::asio::traits::set_error_member;
  66. void set_error();
  67. enum overload_type
  68. {
  69. call_member,
  70. call_free,
  71. ill_formed
  72. };
  73. template <typename R, typename E, typename = void, typename = void>
  74. struct call_traits
  75. {
  76. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  77. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  78. typedef void result_type;
  79. };
  80. template <typename R, typename E>
  81. struct call_traits<R, void(E),
  82. typename enable_if<
  83. set_error_member<R, E>::is_valid
  84. >::type> :
  85. set_error_member<R, E>
  86. {
  87. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
  88. };
  89. template <typename R, typename E>
  90. struct call_traits<R, void(E),
  91. typename enable_if<
  92. !set_error_member<R, E>::is_valid
  93. >::type,
  94. typename enable_if<
  95. set_error_free<R, E>::is_valid
  96. >::type> :
  97. set_error_free<R, E>
  98. {
  99. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
  100. };
  101. struct impl
  102. {
  103. #if defined(BOOST_ASIO_HAS_MOVE)
  104. template <typename R, typename E>
  105. BOOST_ASIO_CONSTEXPR typename enable_if<
  106. call_traits<R, void(E)>::overload == call_member,
  107. typename call_traits<R, void(E)>::result_type
  108. >::type
  109. operator()(R&& r, E&& e) const
  110. BOOST_ASIO_NOEXCEPT_IF((
  111. call_traits<R, void(E)>::is_noexcept))
  112. {
  113. return BOOST_ASIO_MOVE_CAST(R)(r).set_error(BOOST_ASIO_MOVE_CAST(E)(e));
  114. }
  115. template <typename R, typename E>
  116. BOOST_ASIO_CONSTEXPR typename enable_if<
  117. call_traits<R, void(E)>::overload == call_free,
  118. typename call_traits<R, void(E)>::result_type
  119. >::type
  120. operator()(R&& r, E&& e) const
  121. BOOST_ASIO_NOEXCEPT_IF((
  122. call_traits<R, void(E)>::is_noexcept))
  123. {
  124. return set_error(BOOST_ASIO_MOVE_CAST(R)(r), BOOST_ASIO_MOVE_CAST(E)(e));
  125. }
  126. #else // defined(BOOST_ASIO_HAS_MOVE)
  127. template <typename R, typename E>
  128. BOOST_ASIO_CONSTEXPR typename enable_if<
  129. call_traits<R&, void(const E&)>::overload == call_member,
  130. typename call_traits<R&, void(const E&)>::result_type
  131. >::type
  132. operator()(R& r, const E& e) const
  133. BOOST_ASIO_NOEXCEPT_IF((
  134. call_traits<R&, void(const E&)>::is_noexcept))
  135. {
  136. return r.set_error(e);
  137. }
  138. template <typename R, typename E>
  139. BOOST_ASIO_CONSTEXPR typename enable_if<
  140. call_traits<const R&, void(const E&)>::overload == call_member,
  141. typename call_traits<const R&, void(const E&)>::result_type
  142. >::type
  143. operator()(const R& r, const E& e) const
  144. BOOST_ASIO_NOEXCEPT_IF((
  145. call_traits<const R&, void(const E&)>::is_noexcept))
  146. {
  147. return r.set_error(e);
  148. }
  149. template <typename R, typename E>
  150. BOOST_ASIO_CONSTEXPR typename enable_if<
  151. call_traits<R&, void(const E&)>::overload == call_free,
  152. typename call_traits<R&, void(const E&)>::result_type
  153. >::type
  154. operator()(R& r, const E& e) const
  155. BOOST_ASIO_NOEXCEPT_IF((
  156. call_traits<R&, void(const E&)>::is_noexcept))
  157. {
  158. return set_error(r, e);
  159. }
  160. template <typename R, typename E>
  161. BOOST_ASIO_CONSTEXPR typename enable_if<
  162. call_traits<const R&, void(const E&)>::overload == call_free,
  163. typename call_traits<const R&, void(const E&)>::result_type
  164. >::type
  165. operator()(const R& r, const E& e) const
  166. BOOST_ASIO_NOEXCEPT_IF((
  167. call_traits<const R&, void(const E&)>::is_noexcept))
  168. {
  169. return set_error(r, e);
  170. }
  171. #endif // defined(BOOST_ASIO_HAS_MOVE)
  172. };
  173. template <typename T = impl>
  174. struct static_instance
  175. {
  176. static const T instance;
  177. };
  178. template <typename T>
  179. const T static_instance<T>::instance = {};
  180. } // namespace asio_execution_set_error_fn
  181. namespace boost {
  182. namespace asio {
  183. namespace execution {
  184. namespace {
  185. static BOOST_ASIO_CONSTEXPR const asio_execution_set_error_fn::impl&
  186. set_error = asio_execution_set_error_fn::static_instance<>::instance;
  187. } // namespace
  188. template <typename R, typename E>
  189. struct can_set_error :
  190. integral_constant<bool,
  191. asio_execution_set_error_fn::call_traits<R, void(E)>::overload !=
  192. asio_execution_set_error_fn::ill_formed>
  193. {
  194. };
  195. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  196. template <typename R, typename E>
  197. constexpr bool can_set_error_v = can_set_error<R, E>::value;
  198. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  199. template <typename R, typename E>
  200. struct is_nothrow_set_error :
  201. integral_constant<bool,
  202. asio_execution_set_error_fn::call_traits<R, void(E)>::is_noexcept>
  203. {
  204. };
  205. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  206. template <typename R, typename E>
  207. constexpr bool is_nothrow_set_error_v
  208. = is_nothrow_set_error<R, E>::value;
  209. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  210. } // namespace execution
  211. } // namespace asio
  212. } // namespace boost
  213. #endif // defined(GENERATING_DOCUMENTATION)
  214. #include <boost/asio/detail/pop_options.hpp>
  215. #endif // BOOST_ASIO_EXECUTION_SET_ERROR_HPP