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