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