1 | // |
2 | // query.hpp |
3 | // ~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 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 boost_asio_query_fn { |
104 | |
105 | using boost::asio::conditional_t; |
106 | using boost::asio::decay_t; |
107 | using boost::asio::declval; |
108 | using boost::asio::enable_if_t; |
109 | using boost::asio::is_applicable_property; |
110 | using boost::asio::traits::query_free; |
111 | using boost::asio::traits::query_member; |
112 | using boost::asio::traits::static_query; |
113 | |
114 | void query(); |
115 | |
116 | enum overload_type |
117 | { |
118 | static_value, |
119 | call_member, |
120 | call_free, |
121 | ill_formed |
122 | }; |
123 | |
124 | template <typename Impl, typename T, typename Properties, |
125 | typename = void, typename = void, typename = void, typename = void> |
126 | struct call_traits |
127 | { |
128 | static constexpr overload_type overload = ill_formed; |
129 | static constexpr bool is_noexcept = false; |
130 | typedef void result_type; |
131 | }; |
132 | |
133 | template <typename Impl, typename T, typename Property> |
134 | struct call_traits<Impl, T, void(Property), |
135 | enable_if_t< |
136 | is_applicable_property< |
137 | decay_t<T>, |
138 | decay_t<Property> |
139 | >::value |
140 | >, |
141 | enable_if_t< |
142 | static_query<T, Property>::is_valid |
143 | >> : |
144 | static_query<T, Property> |
145 | { |
146 | static constexpr overload_type overload = static_value; |
147 | }; |
148 | |
149 | template <typename Impl, typename T, typename Property> |
150 | struct call_traits<Impl, T, void(Property), |
151 | enable_if_t< |
152 | is_applicable_property< |
153 | decay_t<T>, |
154 | decay_t<Property> |
155 | >::value |
156 | >, |
157 | enable_if_t< |
158 | !static_query<T, Property>::is_valid |
159 | >, |
160 | enable_if_t< |
161 | query_member<typename Impl::template proxy<T>::type, Property>::is_valid |
162 | >> : |
163 | query_member<typename Impl::template proxy<T>::type, Property> |
164 | { |
165 | static constexpr overload_type overload = call_member; |
166 | }; |
167 | |
168 | template <typename Impl, typename T, typename Property> |
169 | struct call_traits<Impl, T, void(Property), |
170 | enable_if_t< |
171 | is_applicable_property< |
172 | decay_t<T>, |
173 | decay_t<Property> |
174 | >::value |
175 | >, |
176 | enable_if_t< |
177 | !static_query<T, Property>::is_valid |
178 | >, |
179 | enable_if_t< |
180 | !query_member<typename Impl::template proxy<T>::type, Property>::is_valid |
181 | >, |
182 | enable_if_t< |
183 | query_free<T, Property>::is_valid |
184 | >> : |
185 | query_free<T, Property> |
186 | { |
187 | static constexpr overload_type overload = call_free; |
188 | }; |
189 | |
190 | struct impl |
191 | { |
192 | template <typename T> |
193 | struct proxy |
194 | { |
195 | #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
196 | struct type |
197 | { |
198 | template <typename P> |
199 | auto query(P&& p) |
200 | noexcept( |
201 | noexcept( |
202 | declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) |
203 | ) |
204 | ) |
205 | -> decltype( |
206 | declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) |
207 | ); |
208 | }; |
209 | #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
210 | typedef T type; |
211 | #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) |
212 | }; |
213 | |
214 | template <typename T, typename Property> |
215 | BOOST_ASIO_NODISCARD constexpr enable_if_t< |
216 | call_traits<impl, T, void(Property)>::overload == static_value, |
217 | typename call_traits<impl, T, void(Property)>::result_type |
218 | > |
219 | operator()(T&&, Property&&) const |
220 | noexcept(call_traits<impl, T, void(Property)>::is_noexcept) |
221 | { |
222 | return static_query<decay_t<T>, decay_t<Property>>::value(); |
223 | } |
224 | |
225 | template <typename T, typename Property> |
226 | BOOST_ASIO_NODISCARD constexpr enable_if_t< |
227 | call_traits<impl, T, void(Property)>::overload == call_member, |
228 | typename call_traits<impl, T, void(Property)>::result_type |
229 | > |
230 | operator()(T&& t, Property&& p) const |
231 | noexcept(call_traits<impl, T, void(Property)>::is_noexcept) |
232 | { |
233 | return static_cast<T&&>(t).query(static_cast<Property&&>(p)); |
234 | } |
235 | |
236 | template <typename T, typename Property> |
237 | BOOST_ASIO_NODISCARD constexpr enable_if_t< |
238 | call_traits<impl, T, void(Property)>::overload == call_free, |
239 | typename call_traits<impl, T, void(Property)>::result_type |
240 | > |
241 | operator()(T&& t, Property&& p) const |
242 | noexcept(call_traits<impl, T, void(Property)>::is_noexcept) |
243 | { |
244 | return query(static_cast<T&&>(t), static_cast<Property&&>(p)); |
245 | } |
246 | }; |
247 | |
248 | template <typename T = impl> |
249 | struct static_instance |
250 | { |
251 | static const T instance; |
252 | }; |
253 | |
254 | template <typename T> |
255 | const T static_instance<T>::instance = {}; |
256 | |
257 | } // namespace boost_asio_query_fn |
258 | namespace boost { |
259 | namespace asio { |
260 | namespace { |
261 | |
262 | static constexpr const boost_asio_query_fn::impl& |
263 | query = boost_asio_query_fn::static_instance<>::instance; |
264 | |
265 | } // namespace |
266 | |
267 | typedef boost_asio_query_fn::impl query_t; |
268 | |
269 | template <typename T, typename Property> |
270 | struct can_query : |
271 | integral_constant<bool, |
272 | boost_asio_query_fn::call_traits<query_t, T, void(Property)>::overload != |
273 | boost_asio_query_fn::ill_formed> |
274 | { |
275 | }; |
276 | |
277 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
278 | |
279 | template <typename T, typename Property> |
280 | constexpr bool can_query_v = can_query<T, Property>::value; |
281 | |
282 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
283 | |
284 | template <typename T, typename Property> |
285 | struct is_nothrow_query : |
286 | integral_constant<bool, |
287 | boost_asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept> |
288 | { |
289 | }; |
290 | |
291 | #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
292 | |
293 | template <typename T, typename Property> |
294 | constexpr bool is_nothrow_query_v = is_nothrow_query<T, Property>::value; |
295 | |
296 | #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) |
297 | |
298 | template <typename T, typename Property> |
299 | struct query_result |
300 | { |
301 | typedef typename boost_asio_query_fn::call_traits< |
302 | query_t, T, void(Property)>::result_type type; |
303 | }; |
304 | |
305 | template <typename T, typename Property> |
306 | using query_result_t = typename query_result<T, Property>::type; |
307 | |
308 | } // namespace asio |
309 | } // namespace boost |
310 | |
311 | #endif // defined(GENERATING_DOCUMENTATION) |
312 | |
313 | #include <boost/asio/detail/pop_options.hpp> |
314 | |
315 | #endif // BOOST_ASIO_QUERY_HPP |
316 | |