1//
2// prefer.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_PREFER_HPP
12#define BOOST_ASIO_PREFER_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/prefer_free.hpp>
22#include <boost/asio/traits/prefer_member.hpp>
23#include <boost/asio/traits/require_free.hpp>
24#include <boost/asio/traits/require_member.hpp>
25#include <boost/asio/traits/static_require.hpp>
26
27#include <boost/asio/detail/push_options.hpp>
28
29#if defined(GENERATING_DOCUMENTATION)
30
31namespace boost {
32namespace asio {
33
34/// A customisation point that attempts to apply a property to an object.
35/**
36 * The name <tt>prefer</tt> denotes a customisation point object. The
37 * expression <tt>boost::asio::prefer(E, P0, Pn...)</tt> for some subexpressions
38 * <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt> represents <tt>N</tt>
39 * subexpressions (where <tt>N</tt> is 0 or more, and with types <tt>T =
40 * decay_t<decltype(E)></tt> and <tt>Prop0 = decay_t<decltype(P0)></tt>) is
41 * expression-equivalent to:
42 *
43 * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_preferable</tt> is
44 * not a well-formed constant expression with value <tt>true</tt>,
45 * <tt>boost::asio::prefer(E, P0, Pn...)</tt> is ill-formed.
46 *
47 * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt> and the expression
48 * <tt>Prop0::template static_query_v<T> == Prop0::value()</tt> is a
49 * well-formed constant expression with value <tt>true</tt>.
50 *
51 * @li Otherwise, <tt>(E).require(P0)</tt> if <tt>N == 0</tt> and the expression
52 * <tt>(E).require(P0)</tt> is a valid expression.
53 *
54 * @li Otherwise, <tt>require(E, P0)</tt> if <tt>N == 0</tt> and the expression
55 * <tt>require(E, P0)</tt> is a valid expression with overload resolution
56 * performed in a context that does not include the declaration of the
57 * <tt>require</tt> customization point object.
58 *
59 * @li Otherwise, <tt>(E).prefer(P0)</tt> if <tt>N == 0</tt> and the expression
60 * <tt>(E).prefer(P0)</tt> is a valid expression.
61 *
62 * @li Otherwise, <tt>prefer(E, P0)</tt> if <tt>N == 0</tt> and the expression
63 * <tt>prefer(E, P0)</tt> is a valid expression with overload resolution
64 * performed in a context that does not include the declaration of the
65 * <tt>prefer</tt> customization point object.
66 *
67 * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt>.
68 *
69 * @li Otherwise,
70 * <tt>boost::asio::prefer(boost::asio::prefer(E, P0), Pn...)</tt>
71 * if <tt>N > 0</tt> and the expression
72 * <tt>boost::asio::prefer(boost::asio::prefer(E, P0), Pn...)</tt>
73 * is a valid expression.
74 *
75 * @li Otherwise, <tt>boost::asio::prefer(E, P0, Pn...)</tt> is ill-formed.
76 */
77inline constexpr unspecified prefer = unspecified;
78
79/// A type trait that determines whether a @c prefer expression is well-formed.
80/**
81 * Class template @c can_prefer is a trait that is derived from
82 * @c true_type if the expression <tt>boost::asio::prefer(std::declval<T>(),
83 * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type.
84 */
85template <typename T, typename... Properties>
86struct can_prefer :
87 integral_constant<bool, automatically_determined>
88{
89};
90
91/// A type trait that determines whether a @c prefer expression will not throw.
92/**
93 * Class template @c is_nothrow_prefer is a trait that is derived from
94 * @c true_type if the expression <tt>boost::asio::prefer(std::declval<T>(),
95 * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type.
96 */
97template <typename T, typename... Properties>
98struct is_nothrow_prefer :
99 integral_constant<bool, automatically_determined>
100{
101};
102
103/// A type trait that determines the result type of a @c prefer expression.
104/**
105 * Class template @c prefer_result is a trait that determines the result
106 * type of the expression <tt>boost::asio::prefer(std::declval<T>(),
107 * std::declval<Properties>()...)</tt>.
108 */
109template <typename T, typename... Properties>
110struct prefer_result
111{
112 /// The result of the @c prefer expression.
113 typedef automatically_determined type;
114};
115
116} // namespace asio
117} // namespace boost
118
119#else // defined(GENERATING_DOCUMENTATION)
120
121namespace boost_asio_prefer_fn {
122
123using boost::asio::conditional_t;
124using boost::asio::decay_t;
125using boost::asio::declval;
126using boost::asio::enable_if_t;
127using boost::asio::is_applicable_property;
128using boost::asio::traits::prefer_free;
129using boost::asio::traits::prefer_member;
130using boost::asio::traits::require_free;
131using boost::asio::traits::require_member;
132using boost::asio::traits::static_require;
133
134void prefer();
135void require();
136
137enum overload_type
138{
139 identity,
140 call_require_member,
141 call_require_free,
142 call_prefer_member,
143 call_prefer_free,
144 two_props,
145 n_props,
146 ill_formed
147};
148
149template <typename Impl, typename T, typename Properties,
150 typename = void, typename = void, typename = void, typename = void,
151 typename = void, typename = void, typename = void>
152struct call_traits
153{
154 static constexpr overload_type overload = ill_formed;
155 static constexpr bool is_noexcept = false;
156 typedef void result_type;
157};
158
159template <typename Impl, typename T, typename Property>
160struct call_traits<Impl, T, void(Property),
161 enable_if_t<
162 is_applicable_property<
163 decay_t<T>,
164 decay_t<Property>
165 >::value
166 >,
167 enable_if_t<
168 decay_t<Property>::is_preferable
169 >,
170 enable_if_t<
171 static_require<T, Property>::is_valid
172 >>
173{
174 static constexpr overload_type overload = identity;
175 static constexpr bool is_noexcept = true;
176
177 typedef T&& result_type;
178};
179
180template <typename Impl, typename T, typename Property>
181struct call_traits<Impl, T, void(Property),
182 enable_if_t<
183 is_applicable_property<
184 decay_t<T>,
185 decay_t<Property>
186 >::value
187 >,
188 enable_if_t<
189 decay_t<Property>::is_preferable
190 >,
191 enable_if_t<
192 !static_require<T, Property>::is_valid
193 >,
194 enable_if_t<
195 require_member<typename Impl::template proxy<T>::type, Property>::is_valid
196 >> :
197 require_member<typename Impl::template proxy<T>::type, Property>
198{
199 static constexpr overload_type overload = call_require_member;
200};
201
202template <typename Impl, typename T, typename Property>
203struct call_traits<Impl, T, void(Property),
204 enable_if_t<
205 is_applicable_property<
206 decay_t<T>,
207 decay_t<Property>
208 >::value
209 >,
210 enable_if_t<
211 decay_t<Property>::is_preferable
212 >,
213 enable_if_t<
214 !static_require<T, Property>::is_valid
215 >,
216 enable_if_t<
217 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
218 >,
219 enable_if_t<
220 require_free<T, Property>::is_valid
221 >> :
222 require_free<T, Property>
223{
224 static constexpr overload_type overload = call_require_free;
225};
226
227template <typename Impl, typename T, typename Property>
228struct call_traits<Impl, T, void(Property),
229 enable_if_t<
230 is_applicable_property<
231 decay_t<T>,
232 decay_t<Property>
233 >::value
234 >,
235 enable_if_t<
236 decay_t<Property>::is_preferable
237 >,
238 enable_if_t<
239 !static_require<T, Property>::is_valid
240 >,
241 enable_if_t<
242 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
243 >,
244 enable_if_t<
245 !require_free<T, Property>::is_valid
246 >,
247 enable_if_t<
248 prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
249 >> :
250 prefer_member<typename Impl::template proxy<T>::type, Property>
251{
252 static constexpr overload_type overload = call_prefer_member;
253};
254
255template <typename Impl, typename T, typename Property>
256struct call_traits<Impl, T, void(Property),
257 enable_if_t<
258 is_applicable_property<
259 decay_t<T>,
260 decay_t<Property>
261 >::value
262 >,
263 enable_if_t<
264 decay_t<Property>::is_preferable
265 >,
266 enable_if_t<
267 !static_require<T, Property>::is_valid
268 >,
269 enable_if_t<
270 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
271 >,
272 enable_if_t<
273 !require_free<T, Property>::is_valid
274 >,
275 enable_if_t<
276 !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
277 >,
278 enable_if_t<
279 prefer_free<T, Property>::is_valid
280 >> :
281 prefer_free<T, Property>
282{
283 static constexpr overload_type overload = call_prefer_free;
284};
285
286template <typename Impl, typename T, typename Property>
287struct call_traits<Impl, T, void(Property),
288 enable_if_t<
289 is_applicable_property<
290 decay_t<T>,
291 decay_t<Property>
292 >::value
293 >,
294 enable_if_t<
295 decay_t<Property>::is_preferable
296 >,
297 enable_if_t<
298 !static_require<T, Property>::is_valid
299 >,
300 enable_if_t<
301 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
302 >,
303 enable_if_t<
304 !require_free<T, Property>::is_valid
305 >,
306 enable_if_t<
307 !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
308 >,
309 enable_if_t<
310 !prefer_free<T, Property>::is_valid
311 >>
312{
313 static constexpr overload_type overload = identity;
314 static constexpr bool is_noexcept = true;
315
316 typedef T&& result_type;
317};
318
319template <typename Impl, typename T, typename P0, typename P1>
320struct call_traits<Impl, T, void(P0, P1),
321 enable_if_t<
322 call_traits<Impl, T, void(P0)>::overload != ill_formed
323 >,
324 enable_if_t<
325 call_traits<
326 Impl,
327 typename call_traits<Impl, T, void(P0)>::result_type,
328 void(P1)
329 >::overload != ill_formed
330 >>
331{
332 static constexpr overload_type overload = two_props;
333
334 static constexpr bool is_noexcept =
335 (
336 call_traits<Impl, T, void(P0)>::is_noexcept
337 &&
338 call_traits<
339 Impl,
340 typename call_traits<Impl, T, void(P0)>::result_type,
341 void(P1)
342 >::is_noexcept
343 );
344
345 typedef decay_t<
346 typename call_traits<
347 Impl,
348 typename call_traits<Impl, T, void(P0)>::result_type,
349 void(P1)
350 >::result_type
351 > result_type;
352};
353
354template <typename Impl, typename T, typename P0,
355 typename P1, typename... PN>
356struct call_traits<Impl, T, void(P0, P1, PN...),
357 enable_if_t<
358 call_traits<Impl, T, void(P0)>::overload != ill_formed
359 >,
360 enable_if_t<
361 call_traits<
362 Impl,
363 typename call_traits<Impl, T, void(P0)>::result_type,
364 void(P1, PN...)
365 >::overload != ill_formed
366 >>
367{
368 static constexpr overload_type overload = n_props;
369
370 static constexpr bool is_noexcept =
371 (
372 call_traits<Impl, T, void(P0)>::is_noexcept
373 &&
374 call_traits<
375 Impl,
376 typename call_traits<Impl, T, void(P0)>::result_type,
377 void(P1, PN...)
378 >::is_noexcept
379 );
380
381 typedef decay_t<
382 typename call_traits<
383 Impl,
384 typename call_traits<Impl, T, void(P0)>::result_type,
385 void(P1, PN...)
386 >::result_type
387 > result_type;
388};
389
390struct impl
391{
392 template <typename T>
393 struct proxy
394 {
395#if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \
396 && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
397 struct type
398 {
399 template <typename P>
400 auto require(P&& p)
401 noexcept(
402 noexcept(
403 declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p))
404 )
405 )
406 -> decltype(
407 declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p))
408 );
409
410 template <typename P>
411 auto prefer(P&& p)
412 noexcept(
413 noexcept(
414 declval<conditional_t<true, T, P>>().prefer(static_cast<P&&>(p))
415 )
416 )
417 -> decltype(
418 declval<conditional_t<true, T, P>>().prefer(static_cast<P&&>(p))
419 );
420 };
421#else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
422 // && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
423 typedef T type;
424#endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
425 // && defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
426 };
427
428 template <typename T, typename Property>
429 BOOST_ASIO_NODISCARD constexpr enable_if_t<
430 call_traits<impl, T, void(Property)>::overload == identity,
431 typename call_traits<impl, T, void(Property)>::result_type
432 >
433 operator()(T&& t, Property&&) const
434 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
435 {
436 return static_cast<T&&>(t);
437 }
438
439 template <typename T, typename Property>
440 BOOST_ASIO_NODISCARD constexpr enable_if_t<
441 call_traits<impl, T, void(Property)>::overload == call_require_member,
442 typename call_traits<impl, T, void(Property)>::result_type
443 >
444 operator()(T&& t, Property&& p) const
445 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
446 {
447 return static_cast<T&&>(t).require(static_cast<Property&&>(p));
448 }
449
450 template <typename T, typename Property>
451 BOOST_ASIO_NODISCARD constexpr enable_if_t<
452 call_traits<impl, T, void(Property)>::overload == call_require_free,
453 typename call_traits<impl, T, void(Property)>::result_type
454 >
455 operator()(T&& t, Property&& p) const
456 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
457 {
458 return require(static_cast<T&&>(t), static_cast<Property&&>(p));
459 }
460
461 template <typename T, typename Property>
462 BOOST_ASIO_NODISCARD constexpr enable_if_t<
463 call_traits<impl, T, void(Property)>::overload == call_prefer_member,
464 typename call_traits<impl, T, void(Property)>::result_type
465 >
466 operator()(T&& t, Property&& p) const
467 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
468 {
469 return static_cast<T&&>(t).prefer(static_cast<Property&&>(p));
470 }
471
472 template <typename T, typename Property>
473 BOOST_ASIO_NODISCARD constexpr enable_if_t<
474 call_traits<impl, T, void(Property)>::overload == call_prefer_free,
475 typename call_traits<impl, T, void(Property)>::result_type
476 >
477 operator()(T&& t, Property&& p) const
478 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
479 {
480 return prefer(static_cast<T&&>(t), static_cast<Property&&>(p));
481 }
482
483 template <typename T, typename P0, typename P1>
484 BOOST_ASIO_NODISCARD constexpr enable_if_t<
485 call_traits<impl, T, void(P0, P1)>::overload == two_props,
486 typename call_traits<impl, T, void(P0, P1)>::result_type
487 >
488 operator()(T&& t, P0&& p0, P1&& p1) const
489 noexcept(call_traits<impl, T, void(P0, P1)>::is_noexcept)
490 {
491 return (*this)(
492 (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)),
493 static_cast<P1&&>(p1));
494 }
495
496 template <typename T, typename P0, typename P1,
497 typename... PN>
498 BOOST_ASIO_NODISCARD constexpr enable_if_t<
499 call_traits<impl, T, void(P0, P1, PN...)>::overload == n_props,
500 typename call_traits<impl, T, void(P0, P1, PN...)>::result_type
501 >
502 operator()(T&& t, P0&& p0, P1&& p1, PN&&... pn) const
503 noexcept(call_traits<impl, T, void(P0, P1, PN...)>::is_noexcept)
504 {
505 return (*this)(
506 (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)),
507 static_cast<P1&&>(p1), static_cast<PN&&>(pn)...);
508 }
509};
510
511template <typename T = impl>
512struct static_instance
513{
514 static const T instance;
515};
516
517template <typename T>
518const T static_instance<T>::instance = {};
519
520} // namespace boost_asio_prefer_fn
521namespace boost {
522namespace asio {
523namespace {
524
525static constexpr const boost_asio_prefer_fn::impl&
526 prefer = boost_asio_prefer_fn::static_instance<>::instance;
527
528} // namespace
529
530typedef boost_asio_prefer_fn::impl prefer_t;
531
532template <typename T, typename... Properties>
533struct can_prefer :
534 integral_constant<bool,
535 boost_asio_prefer_fn::call_traits<
536 prefer_t, T, void(Properties...)>::overload
537 != boost_asio_prefer_fn::ill_formed>
538{
539};
540
541#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
542
543template <typename T, typename... Properties>
544constexpr bool can_prefer_v
545 = can_prefer<T, Properties...>::value;
546
547#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
548
549template <typename T, typename... Properties>
550struct is_nothrow_prefer :
551 integral_constant<bool,
552 boost_asio_prefer_fn::call_traits<
553 prefer_t, T, void(Properties...)>::is_noexcept>
554{
555};
556
557#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
558
559template <typename T, typename... Properties>
560constexpr bool is_nothrow_prefer_v = is_nothrow_prefer<T, Properties...>::value;
561
562#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
563
564template <typename T, typename... Properties>
565struct prefer_result
566{
567 typedef typename boost_asio_prefer_fn::call_traits<
568 prefer_t, T, void(Properties...)>::result_type type;
569};
570
571template <typename T, typename... Properties>
572using prefer_result_t = typename prefer_result<T, Properties...>::type;
573
574} // namespace asio
575} // namespace boost
576
577#endif // defined(GENERATING_DOCUMENTATION)
578
579#include <boost/asio/detail/pop_options.hpp>
580
581#endif // BOOST_ASIO_PREFER_HPP
582

source code of boost/libs/asio/include/boost/asio/prefer.hpp