1//
2// require_concept.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_CONCEPT_HPP
12#define BOOST_ASIO_REQUIRE_CONCEPT_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_concept_member.hpp>
22#include <boost/asio/traits/require_concept_free.hpp>
23#include <boost/asio/traits/static_require_concept.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-enforcing property to an
33/// object.
34/**
35 * The name <tt>require_concept</tt> denotes a customization point object. The
36 * expression <tt>boost::asio::require_concept(E, P)</tt> for some
37 * subexpressions <tt>E</tt> and <tt>P</tt> (with types <tt>T =
38 * decay_t<decltype(E)></tt> and <tt>Prop = decay_t<decltype(P)></tt>) is
39 * expression-equivalent to:
40 *
41 * @li If <tt>is_applicable_property_v<T, Prop> &&
42 * Prop::is_requirable_concept</tt> is not a well-formed constant expression
43 * with value <tt>true</tt>, <tt>boost::asio::require_concept(E, P)</tt> is
44 * ill-formed.
45 *
46 * @li Otherwise, <tt>E</tt> if the expression <tt>Prop::template
47 * static_query_v<T> == Prop::value()</tt> is a well-formed constant
48 * expression with value <tt>true</tt>.
49 *
50 * @li Otherwise, <tt>(E).require_concept(P)</tt> if the expression
51 * <tt>(E).require_concept(P)</tt> is well-formed.
52 *
53 * @li Otherwise, <tt>require_concept(E, P)</tt> if the expression
54 * <tt>require_concept(E, P)</tt> is a valid expression with overload
55 * resolution performed in a context that does not include the declaration
56 * of the <tt>require_concept</tt> customization point object.
57 *
58 * @li Otherwise, <tt>boost::asio::require_concept(E, P)</tt> is ill-formed.
59 */
60inline constexpr unspecified require_concept = unspecified;
61
62/// A type trait that determines whether a @c require_concept expression is
63/// well-formed.
64/**
65 * Class template @c can_require_concept is a trait that is derived from
66 * @c true_type if the expression
67 * <tt>boost::asio::require_concept(std::declval<T>(),
68 * std::declval<Property>())</tt> is well formed; otherwise @c false_type.
69 */
70template <typename T, typename Property>
71struct can_require_concept :
72 integral_constant<bool, automatically_determined>
73{
74};
75
76/// A type trait that determines whether a @c require_concept expression will
77/// not throw.
78/**
79 * Class template @c is_nothrow_require_concept is a trait that is derived from
80 * @c true_type if the expression
81 * <tt>boost::asio::require_concept(std::declval<T>(),
82 * std::declval<Property>())</tt> is @c noexcept; otherwise @c false_type.
83 */
84template <typename T, typename Property>
85struct is_nothrow_require_concept :
86 integral_constant<bool, automatically_determined>
87{
88};
89
90/// A type trait that determines the result type of a @c require_concept
91/// expression.
92/**
93 * Class template @c require_concept_result is a trait that determines the
94 * result type of the expression
95 * <tt>boost::asio::require_concept(std::declval<T>(),
96 * std::declval<Property>())</tt>.
97 */
98template <typename T, typename Property>
99struct require_concept_result
100{
101 /// The result of the @c require_concept 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_concept_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_concept_free;
118using boost::asio::traits::require_concept_member;
119using boost::asio::traits::static_require_concept;
120
121void require_concept();
122
123enum overload_type
124{
125 identity,
126 call_member,
127 call_free,
128 ill_formed
129};
130
131template <typename Impl, typename T, typename Properties, typename = void,
132 typename = void, typename = void, typename = void, typename = void>
133struct call_traits
134{
135 static constexpr overload_type overload = ill_formed;
136 static constexpr bool is_noexcept = false;
137 typedef void result_type;
138};
139
140template <typename Impl, typename T, typename Property>
141struct call_traits<Impl, T, void(Property),
142 enable_if_t<
143 is_applicable_property<
144 decay_t<T>,
145 decay_t<Property>
146 >::value
147 >,
148 enable_if_t<
149 decay_t<Property>::is_requirable_concept
150 >,
151 enable_if_t<
152 static_require_concept<T, Property>::is_valid
153 >>
154{
155 static constexpr overload_type overload = identity;
156 static constexpr bool is_noexcept = true;
157 typedef T&& result_type;
158};
159
160template <typename Impl, typename T, typename Property>
161struct call_traits<Impl, T, void(Property),
162 enable_if_t<
163 is_applicable_property<
164 decay_t<T>,
165 decay_t<Property>
166 >::value
167 >,
168 enable_if_t<
169 decay_t<Property>::is_requirable_concept
170 >,
171 enable_if_t<
172 !static_require_concept<T, Property>::is_valid
173 >,
174 enable_if_t<
175 require_concept_member<
176 typename Impl::template proxy<T>::type,
177 Property
178 >::is_valid
179 >> :
180 require_concept_member<
181 typename Impl::template proxy<T>::type,
182 Property
183 >
184{
185 static constexpr overload_type overload = call_member;
186};
187
188template <typename Impl, typename T, typename Property>
189struct call_traits<Impl, T, void(Property),
190 enable_if_t<
191 is_applicable_property<
192 decay_t<T>,
193 decay_t<Property>
194 >::value
195 >,
196 enable_if_t<
197 decay_t<Property>::is_requirable_concept
198 >,
199 enable_if_t<
200 !static_require_concept<T, Property>::is_valid
201 >,
202 enable_if_t<
203 !require_concept_member<
204 typename Impl::template proxy<T>::type,
205 Property
206 >::is_valid
207 >,
208 enable_if_t<
209 require_concept_free<T, Property>::is_valid
210 >> :
211 require_concept_free<T, Property>
212{
213 static constexpr overload_type overload = call_free;
214};
215
216struct impl
217{
218 template <typename T>
219 struct proxy
220 {
221#if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
222 struct type
223 {
224 template <typename P>
225 auto require_concept(P&& p)
226 noexcept(
227 noexcept(
228 declval<conditional_t<true, T, P>>().require_concept(
229 static_cast<P&&>(p))
230 )
231 )
232 -> decltype(
233 declval<conditional_t<true, T, P>>().require_concept(
234 static_cast<P&&>(p))
235 );
236 };
237#else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
238 typedef T type;
239#endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
240 };
241
242 template <typename T, typename Property>
243 BOOST_ASIO_NODISCARD constexpr enable_if_t<
244 call_traits<impl, T, void(Property)>::overload == identity,
245 typename call_traits<impl, T, void(Property)>::result_type
246 >
247 operator()(T&& t, Property&&) const
248 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
249 {
250 return static_cast<T&&>(t);
251 }
252
253 template <typename T, typename Property>
254 BOOST_ASIO_NODISCARD constexpr enable_if_t<
255 call_traits<impl, T, void(Property)>::overload == call_member,
256 typename call_traits<impl, T, void(Property)>::result_type
257 >
258 operator()(T&& t, Property&& p) const
259 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
260 {
261 return static_cast<T&&>(t).require_concept(static_cast<Property&&>(p));
262 }
263
264 template <typename T, typename Property>
265 BOOST_ASIO_NODISCARD constexpr enable_if_t<
266 call_traits<impl, T, void(Property)>::overload == call_free,
267 typename call_traits<impl, T, void(Property)>::result_type
268 >
269 operator()(T&& t, Property&& p) const
270 noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
271 {
272 return require_concept(static_cast<T&&>(t), static_cast<Property&&>(p));
273 }
274};
275
276template <typename T = impl>
277struct static_instance
278{
279 static const T instance;
280};
281
282template <typename T>
283const T static_instance<T>::instance = {};
284
285} // namespace boost_asio_require_concept_fn
286namespace boost {
287namespace asio {
288namespace {
289
290static constexpr const boost_asio_require_concept_fn::impl&
291 require_concept = boost_asio_require_concept_fn::static_instance<>::instance;
292
293} // namespace
294
295typedef boost_asio_require_concept_fn::impl require_concept_t;
296
297template <typename T, typename Property>
298struct can_require_concept :
299 integral_constant<bool,
300 boost_asio_require_concept_fn::call_traits<
301 require_concept_t, T, void(Property)>::overload !=
302 boost_asio_require_concept_fn::ill_formed>
303{
304};
305
306#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
307
308template <typename T, typename Property>
309constexpr bool can_require_concept_v = can_require_concept<T, Property>::value;
310
311#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
312
313template <typename T, typename Property>
314struct is_nothrow_require_concept :
315 integral_constant<bool,
316 boost_asio_require_concept_fn::call_traits<
317 require_concept_t, T, void(Property)>::is_noexcept>
318{
319};
320
321#if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
322
323template <typename T, typename Property>
324constexpr bool is_nothrow_require_concept_v
325 = is_nothrow_require_concept<T, Property>::value;
326
327#endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
328
329template <typename T, typename Property>
330struct require_concept_result
331{
332 typedef typename boost_asio_require_concept_fn::call_traits<
333 require_concept_t, T, void(Property)>::result_type type;
334};
335
336template <typename T, typename Property>
337using require_concept_result_t =
338 typename require_concept_result<T, Property>::type;
339
340} // namespace asio
341} // namespace boost
342
343#endif // defined(GENERATING_DOCUMENTATION)
344
345#include <boost/asio/detail/pop_options.hpp>
346
347#endif // BOOST_ASIO_REQUIRE_CONCEPT_HPP
348

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