1 // 2 // query.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_QUERY_HPP 12 #define BOOST_ASIO_QUERY_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/is_applicable_property.hpp> 21 #include <boost/asio/traits/query_member.hpp> 22 #include <boost/asio/traits/query_free.hpp> 23 #include <boost/asio/traits/static_query.hpp> 24 25 #include <boost/asio/detail/push_options.hpp> 26 27 #if defined(GENERATING_DOCUMENTATION) 28 29 namespace boost { 30 namespace asio { 31 32 /// A customisation point that queries the value of a property. 33 /** 34 * The name <tt>query</tt> denotes a customization point object. The 35 * expression <tt>boost::asio::query(E, P)</tt> for some 36 * subexpressions <tt>E</tt> and <tt>P</tt> (with types <tt>T = 37 * decay_t<decltype(E)></tt> and <tt>Prop = decay_t<decltype(P)></tt>) is 38 * expression-equivalent to: 39 * 40 * @li If <tt>is_applicable_property_v<T, Prop></tt> is not a well-formed 41 * constant expression with value <tt>true</tt>, <tt>boost::asio::query(E, 42 * P)</tt> is ill-formed. 43 * 44 * @li Otherwise, <tt>Prop::template static_query_v<T></tt> if the expression 45 * <tt>Prop::template static_query_v<T></tt> is a well-formed constant 46 * expression. 47 * 48 * @li Otherwise, <tt>(E).query(P)</tt> if the expression 49 * <tt>(E).query(P)</tt> is well-formed. 50 * 51 * @li Otherwise, <tt>query(E, P)</tt> if the expression 52 * <tt>query(E, P)</tt> is a valid expression with overload 53 * resolution performed in a context that does not include the declaration 54 * of the <tt>query</tt> customization point object. 55 * 56 * @li Otherwise, <tt>boost::asio::query(E, P)</tt> is ill-formed. 57 */ 58 inline constexpr unspecified query = unspecified; 59 60 /// A type trait that determines whether a @c query expression is well-formed. 61 /** 62 * Class template @c can_query is a trait that is derived from 63 * @c true_type if the expression <tt>boost::asio::query(std::declval<T>(), 64 * std::declval<Property>())</tt> is well formed; otherwise @c false_type. 65 */ 66 template <typename T, typename Property> 67 struct can_query : 68 integral_constant<bool, automatically_determined> 69 { 70 }; 71 72 /// A type trait that determines whether a @c query expression will 73 /// not throw. 74 /** 75 * Class template @c is_nothrow_query is a trait that is derived from 76 * @c true_type if the expression <tt>boost::asio::query(std::declval<T>(), 77 * std::declval<Property>())</tt> is @c noexcept; otherwise @c false_type. 78 */ 79 template <typename T, typename Property> 80 struct is_nothrow_query : 81 integral_constant<bool, automatically_determined> 82 { 83 }; 84 85 /// A type trait that determines the result type of a @c query expression. 86 /** 87 * Class template @c query_result is a trait that determines the result 88 * type of the expression <tt>boost::asio::query(std::declval<T>(), 89 * std::declval<Property>())</tt>. 90 */ 91 template <typename T, typename Property> 92 struct query_result 93 { 94 /// The result of the @c query expression. 95 typedef automatically_determined type; 96 }; 97 98 } // namespace asio 99 } // namespace boost 100 101 #else // defined(GENERATING_DOCUMENTATION) 102 103 namespace asio_query_fn { 104 105 using boost::asio::decay; 106 using boost::asio::declval; 107 using boost::asio::enable_if; 108 using boost::asio::is_applicable_property; 109 using boost::asio::traits::query_free; 110 using boost::asio::traits::query_member; 111 using boost::asio::traits::static_query; 112 113 void query(); 114 115 enum overload_type 116 { 117 static_value, 118 call_member, 119 call_free, 120 ill_formed 121 }; 122 123 template <typename T, typename Properties, typename = void> 124 struct call_traits 125 { 126 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); 127 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); 128 typedef void result_type; 129 }; 130 131 template <typename T, typename Property> 132 struct call_traits<T, void(Property), 133 typename enable_if< 134 ( 135 is_applicable_property< 136 typename decay<T>::type, 137 typename decay<Property>::type 138 >::value 139 && 140 static_query<T, Property>::is_valid 141 ) 142 >::type> : 143 static_query<T, Property> 144 { 145 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = static_value); 146 }; 147 148 template <typename T, typename Property> 149 struct call_traits<T, void(Property), 150 typename enable_if< 151 ( 152 is_applicable_property< 153 typename decay<T>::type, 154 typename decay<Property>::type 155 >::value 156 && 157 !static_query<T, Property>::is_valid 158 && 159 query_member<T, Property>::is_valid 160 ) 161 >::type> : 162 query_member<T, Property> 163 { 164 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); 165 }; 166 167 template <typename T, typename Property> 168 struct call_traits<T, void(Property), 169 typename enable_if< 170 ( 171 is_applicable_property< 172 typename decay<T>::type, 173 typename decay<Property>::type 174 >::value 175 && 176 !static_query<T, Property>::is_valid 177 && 178 !query_member<T, Property>::is_valid 179 && 180 query_free<T, Property>::is_valid 181 ) 182 >::type> : 183 query_free<T, Property> 184 { 185 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); 186 }; 187 188 struct impl 189 { 190 template <typename T, typename Property> 191 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 192 call_traits<T, void(Property)>::overload == static_value, 193 typename call_traits<T, void(Property)>::result_type 194 >::type operator ()asio_query_fn::impl195 operator()( 196 BOOST_ASIO_MOVE_ARG(T), 197 BOOST_ASIO_MOVE_ARG(Property)) const 198 BOOST_ASIO_NOEXCEPT_IF(( 199 call_traits<T, void(Property)>::is_noexcept)) 200 { 201 return static_query< 202 typename decay<T>::type, 203 typename decay<Property>::type 204 >::value(); 205 } 206 207 template <typename T, typename Property> 208 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 209 call_traits<T, void(Property)>::overload == call_member, 210 typename call_traits<T, void(Property)>::result_type 211 >::type operator ()asio_query_fn::impl212 operator()( 213 BOOST_ASIO_MOVE_ARG(T) t, 214 BOOST_ASIO_MOVE_ARG(Property) p) const 215 BOOST_ASIO_NOEXCEPT_IF(( 216 call_traits<T, void(Property)>::is_noexcept)) 217 { 218 return BOOST_ASIO_MOVE_CAST(T)(t).query(BOOST_ASIO_MOVE_CAST(Property)(p)); 219 } 220 221 template <typename T, typename Property> 222 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if< 223 call_traits<T, void(Property)>::overload == call_free, 224 typename call_traits<T, void(Property)>::result_type 225 >::type operator ()asio_query_fn::impl226 operator()( 227 BOOST_ASIO_MOVE_ARG(T) t, 228 BOOST_ASIO_MOVE_ARG(Property) p) const 229 BOOST_ASIO_NOEXCEPT_IF(( 230 call_traits<T, void(Property)>::is_noexcept)) 231 { 232 return query(BOOST_ASIO_MOVE_CAST(T)(t), BOOST_ASIO_MOVE_CAST(Property)(p)); 233 } 234 }; 235 236 template <typename T = impl> 237 struct static_instance 238 { 239 static const T instance; 240 }; 241 242 template <typename T> 243 const T static_instance<T>::instance = {}; 244 245 } // namespace asio_query_fn 246 namespace boost { 247 namespace asio { 248 namespace { 249 250 static BOOST_ASIO_CONSTEXPR const asio_query_fn::impl& 251 query = asio_query_fn::static_instance<>::instance; 252 253 } // namespace 254 255 template <typename T, typename Property> 256 struct can_query : 257 integral_constant<bool, 258 asio_query_fn::call_traits<T, void(Property)>::overload != 259 asio_query_fn::ill_formed> 260 { 261 }; 262 263 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 264 265 template <typename T, typename Property> 266 constexpr bool can_query_v 267 = can_query<T, Property>::value; 268 269 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 270 271 template <typename T, typename Property> 272 struct is_nothrow_query : 273 integral_constant<bool, 274 asio_query_fn::call_traits<T, void(Property)>::is_noexcept> 275 { 276 }; 277 278 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 279 280 template <typename T, typename Property> 281 constexpr bool is_nothrow_query_v 282 = is_nothrow_query<T, Property>::value; 283 284 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) 285 286 template <typename T, typename Property> 287 struct query_result 288 { 289 typedef typename asio_query_fn::call_traits< 290 T, void(Property)>::result_type type; 291 }; 292 293 } // namespace asio 294 } // namespace boost 295 296 #endif // defined(GENERATING_DOCUMENTATION) 297 298 #include <boost/asio/detail/pop_options.hpp> 299 300 #endif // BOOST_ASIO_QUERY_HPP 301