1//
2// require.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_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
29namespace boost {
30namespace 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 */
66inline 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 */
74template <typename T, typename... Properties>
75struct 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 */
86template <typename T, typename... Properties>
87struct 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 */
98template <typename T, typename... Properties>
99struct 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
110namespace boost_asio_require_fn {
111
112using boost::asio::conditional_t;
113using boost::asio::decay_t;
114using boost::asio::declval;
115using boost::asio::enable_if_t;
116using boost::asio::is_applicable_property;
117using boost::asio::traits::require_free;
118using boost::asio::traits::require_member;
119using boost::asio::traits::static_require;
120
121void require();
122
123enum overload_type
124{
125 identity,
126 call_member,
127 call_free,
128 two_props,
129 n_props,
130 ill_formed
131};
132
133template <typename Impl, typename T, typename Properties, typename = void,
134 typename = void, typename = void, typename = void, typename = void>
135struct call_traits
136{
137 static constexpr overload_type overload = ill_formed;
138 static constexpr bool is_noexcept = false;
139 typedef void result_type;
140};
141
142template <typename Impl, typename T, typename Property>
143struct call_traits<Impl, T, void(Property),
144 enable_if_t<
145 is_applicable_property<
146 decay_t<T>,
147 decay_t<Property>
148 >::value
149 >,
150 enable_if_t<
151 decay_t<Property>::is_requirable
152 >,
153 enable_if_t<
154 static_require<T, Property>::is_valid
155 >>
156{
157 static constexpr overload_type overload = identity;
158 static constexpr bool is_noexcept = true;
159
160 typedef T&& result_type;
161};
162
163template <typename Impl, typename T, typename Property>
164struct call_traits<Impl, T, void(Property),
165 enable_if_t<
166 is_applicable_property<
167 decay_t<T>,
168 decay_t<Property>
169 >::value
170 >,
171 enable_if_t<
172 decay_t<Property>::is_requirable
173 >,
174 enable_if_t<
175 !static_require<T, Property>::is_valid
176 >,
177 enable_if_t<
178 require_member<typename Impl::template proxy<T>::type, Property>::is_valid
179 >> :
180 require_member<typename Impl::template proxy<T>::type, Property>
181{
182 static constexpr overload_type overload = call_member;
183};
184
185template <typename Impl, typename T, typename Property>
186struct call_traits<Impl, T, void(Property),
187 enable_if_t<
188 is_applicable_property<
189 decay_t<T>,
190 decay_t<Property>
191 >::value
192 >,
193 enable_if_t<
194 decay_t<Property>::is_requirable
195 >,
196 enable_if_t<
197 !static_require<T, Property>::is_valid
198 >,
199 enable_if_t<
200 !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
201 >,
202 enable_if_t<
203 require_free<T, Property>::is_valid
204 >> :
205 require_free<T, Property>
206{
207 static constexpr overload_type overload = call_free;
208};
209
210template <typename Impl, typename T, typename P0, typename P1>
211struct call_traits<Impl, T, void(P0, P1),
212 enable_if_t<
213 call_traits<Impl, T, void(P0)>::overload != ill_formed
214 >,
215 enable_if_t<
216 call_traits<
217 Impl,
218 typename call_traits<Impl, T, void(P0)>::result_type,
219 void(P1)
220 >::overload != ill_formed
221 >>
222{
223 static constexpr overload_type overload = two_props;
224
225 static constexpr bool is_noexcept =
226 (
227 call_traits<Impl, T, void(P0)>::is_noexcept
228 &&
229 call_traits<
230 Impl,
231 typename call_traits<Impl, T, void(P0)>::result_type,
232 void(P1)
233 >::is_noexcept
234 );
235
236 typedef decay_t<
237 typename call_traits<
238 Impl,
239 typename call_traits<Impl, T, void(P0)>::result_type,
240 void(P1)
241 >::result_type
242 > result_type;
243};
244
245template <typename Impl, typename T, typename P0,
246 typename P1, typename... PN>
247struct call_traits<Impl, T, void(P0, P1, PN...),
248 enable_if_t<
249 call_traits<Impl, T, void(P0)>::overload != ill_formed
250 >,
251 enable_if_t<
252 call_traits<
253 Impl,
254 typename call_traits<Impl, T, void(P0)>::result_type,
255 void(P1, PN...)
256 >::overload != ill_formed
257 >>
258{
259 static constexpr overload_type overload = n_props;
260
261 static constexpr bool is_noexcept =
262 (
263 call_traits<Impl, T, void(P0)>::is_noexcept
264 &&
265 call_traits<
266 Impl,
267 typename call_traits<Impl, T, void(P0)>::result_type,
268 void(P1, PN...)
269 >::is_noexcept
270 );
271
272 typedef decay_t<
273 typename call_traits<
274 Impl,
275 typename call_traits<Impl, T, void(P0)>::result_type,
276 void(P1, PN...)
277 >::result_type
278 > result_type;
279};
280
281struct impl
282{
283 template <typename T>
284 struct proxy
285 {
286#if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
287 struct type
288 {
289 template <typename P>
290 auto require(P&& p)
291 noexcept(
292 noexcept(
293 declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p))
294 )
295 )
296 -> decltype(
297 declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p))
298 );
299 };
300#else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
301 typedef T type;
302#endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
303 };
304
305 template <typename T, typename Property>
306 BOOST_ASIO_NODISCARD constexpr enable_if_t<
307 call_traits<impl, T, void(Property)>::overload == identity,
308 typename call_traits<impl, T, void(Property)>::result_type
309 >
310 operator()(T&& t, Property&&) const
311 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
312 {
313 return static_cast<T&&>(t);
314 }
315
316 template <typename T, typename Property>
317 BOOST_ASIO_NODISCARD constexpr enable_if_t<
318 call_traits<impl, T, void(Property)>::overload == call_member,
319 typename call_traits<impl, T, void(Property)>::result_type
320 >
321 operator()(T&& t, Property&& p) const
322 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
323 {
324 return static_cast<T&&>(t).require(static_cast<Property&&>(p));
325 }
326
327 template <typename T, typename Property>
328 BOOST_ASIO_NODISCARD constexpr enable_if_t<
329 call_traits<impl, T, void(Property)>::overload == call_free,
330 typename call_traits<impl, T, void(Property)>::result_type
331 >
332 operator()(T&& t, Property&& p) const
333 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
334 {
335 return require(static_cast<T&&>(t), static_cast<Property&&>(p));
336 }
337
338 template <typename T, typename P0, typename P1>
339 BOOST_ASIO_NODISCARD constexpr enable_if_t<
340 call_traits<impl, T, void(P0, P1)>::overload == two_props,
341 typename call_traits<impl, T, void(P0, P1)>::result_type
342 >
343 operator()(T&& t, P0&& p0, P1&& p1) const
344 noexcept(call_traits<impl, T, void(P0, P1)>::is_noexcept)
345 {
346 return (*this)(
347 (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)),
348 static_cast<P1&&>(p1));
349 }
350
351 template <typename T, typename P0, typename P1,
352 typename... PN>
353 BOOST_ASIO_NODISCARD constexpr enable_if_t<
354 call_traits<impl, T, void(P0, P1, PN...)>::overload == n_props,
355 typename call_traits<impl, T, void(P0, P1, PN...)>::result_type
356 >
357 operator()(T&& t, P0&& p0, P1&& p1, PN&&... pn) const
358 noexcept(call_traits<impl, T, void(P0, P1, PN...)>::is_noexcept)
359 {
360 return (*this)(
361 (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)),
362 static_cast<P1&&>(p1), static_cast<PN&&>(pn)...);
363 }
364};
365
366template <typename T = impl>
367struct static_instance
368{
369 static const T instance;
370};
371
372template <typename T>
373const T static_instance<T>::instance = {};
374
375} // namespace boost_asio_require_fn
376namespace boost {
377namespace asio {
378namespace {
379
380static constexpr const boost_asio_require_fn::impl&
381 require = boost_asio_require_fn::static_instance<>::instance;
382
383} // namespace
384
385typedef boost_asio_require_fn::impl require_t;
386
387template <typename T, typename... Properties>
388struct can_require :
389 integral_constant<bool,
390 boost_asio_require_fn::call_traits<
391 require_t, T, void(Properties...)>::overload
392 != boost_asio_require_fn::ill_formed>
393{
394};
395
396#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
397
398template <typename T, typename... Properties>
399constexpr bool can_require_v
400 = can_require<T, Properties...>::value;
401
402#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
403
404template <typename T, typename... Properties>
405struct is_nothrow_require :
406 integral_constant<bool,
407 boost_asio_require_fn::call_traits<
408 require_t, T, void(Properties...)>::is_noexcept>
409{
410};
411
412#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
413
414template <typename T, typename... Properties>
415constexpr bool is_nothrow_require_v
416 = is_nothrow_require<T, Properties...>::value;
417
418#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
419
420template <typename T, typename... Properties>
421struct require_result
422{
423 typedef typename boost_asio_require_fn::call_traits<
424 require_t, T, void(Properties...)>::result_type type;
425};
426
427template <typename T, typename... Properties>
428using require_result_t = typename require_result<T, Properties...>::type;
429
430} // namespace asio
431} // namespace boost
432
433#endif // defined(GENERATING_DOCUMENTATION)
434
435#include <boost/asio/detail/pop_options.hpp>
436
437#endif // BOOST_ASIO_REQUIRE_HPP
438

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