5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_REQUIRE_CONCEPT_HPP
12 #define BOOST_ASIO_REQUIRE_CONCEPT_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
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>
25 #include <boost/asio/detail/push_options.hpp>
27 #if defined(GENERATING_DOCUMENTATION)
32 /// A customisation point that applies a concept-enforcing property to an
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:
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
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>.
50 * @li Otherwise, <tt>(E).require_concept(P)</tt> if the expression
51 * <tt>(E).require_concept(P)</tt> is well-formed.
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.
58 * @li Otherwise, <tt>boost::asio::require_concept(E, P)</tt> is ill-formed.
60 inline constexpr unspecified require_concept = unspecified;
62 /// A type trait that determines whether a @c require_concept expression is
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.
70 template <typename T, typename Property>
71 struct can_require_concept :
72 integral_constant<bool, automatically_determined>
76 /// A type trait that determines whether a @c require_concept expression will
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.
84 template <typename T, typename Property>
85 struct is_nothrow_require_concept :
86 integral_constant<bool, automatically_determined>
90 /// A type trait that determines the result type of a @c require_concept
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>.
98 template <typename T, typename Property>
99 struct require_concept_result
101 /// The result of the @c require_concept expression.
102 typedef automatically_determined type;
108 #else // defined(GENERATING_DOCUMENTATION)
110 namespace boost_asio_require_concept_fn {
112 using boost::asio::conditional;
113 using boost::asio::decay;
114 using boost::asio::declval;
115 using boost::asio::enable_if;
116 using boost::asio::is_applicable_property;
117 using boost::asio::traits::require_concept_free;
118 using boost::asio::traits::require_concept_member;
119 using boost::asio::traits::static_require_concept;
121 void require_concept();
131 template <typename Impl, typename T, typename Properties, typename = void,
132 typename = void, typename = void, typename = void, typename = void>
135 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
136 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
137 typedef void result_type;
140 template <typename Impl, typename T, typename Property>
141 struct call_traits<Impl, T, void(Property),
143 is_applicable_property<
144 typename decay<T>::type,
145 typename decay<Property>::type
149 decay<Property>::type::is_requirable_concept
152 static_require_concept<T, Property>::is_valid
155 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
156 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
157 typedef BOOST_ASIO_MOVE_ARG(T) result_type;
160 template <typename Impl, typename T, typename Property>
161 struct call_traits<Impl, T, void(Property),
163 is_applicable_property<
164 typename decay<T>::type,
165 typename decay<Property>::type
169 decay<Property>::type::is_requirable_concept
172 !static_require_concept<T, Property>::is_valid
175 require_concept_member<
176 typename Impl::template proxy<T>::type,
180 require_concept_member<
181 typename Impl::template proxy<T>::type,
185 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
188 template <typename Impl, typename T, typename Property>
189 struct call_traits<Impl, T, void(Property),
191 is_applicable_property<
192 typename decay<T>::type,
193 typename decay<Property>::type
197 decay<Property>::type::is_requirable_concept
200 !static_require_concept<T, Property>::is_valid
203 !require_concept_member<
204 typename Impl::template proxy<T>::type,
209 require_concept_free<T, Property>::is_valid
211 require_concept_free<T, Property>
213 BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
218 template <typename T>
221 #if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
224 template <typename P>
225 auto require_concept(BOOST_ASIO_MOVE_ARG(P) p)
228 declval<typename conditional<true, T, P>::type>().require_concept(
229 BOOST_ASIO_MOVE_CAST(P)(p))
233 declval<typename conditional<true, T, P>::type>().require_concept(
234 BOOST_ASIO_MOVE_CAST(P)(p))
237 #else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
239 #endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
242 template <typename T, typename Property>
243 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
244 call_traits<impl, T, void(Property)>::overload == identity,
245 typename call_traits<impl, T, void(Property)>::result_type
248 BOOST_ASIO_MOVE_ARG(T) t,
249 BOOST_ASIO_MOVE_ARG(Property)) const
250 BOOST_ASIO_NOEXCEPT_IF((
251 call_traits<impl, T, void(Property)>::is_noexcept))
253 return BOOST_ASIO_MOVE_CAST(T)(t);
256 template <typename T, typename Property>
257 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
258 call_traits<impl, T, void(Property)>::overload == call_member,
259 typename call_traits<impl, T, void(Property)>::result_type
262 BOOST_ASIO_MOVE_ARG(T) t,
263 BOOST_ASIO_MOVE_ARG(Property) p) const
264 BOOST_ASIO_NOEXCEPT_IF((
265 call_traits<impl, T, void(Property)>::is_noexcept))
267 return BOOST_ASIO_MOVE_CAST(T)(t).require_concept(
268 BOOST_ASIO_MOVE_CAST(Property)(p));
271 template <typename T, typename Property>
272 BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
273 call_traits<impl, T, void(Property)>::overload == call_free,
274 typename call_traits<impl, T, void(Property)>::result_type
277 BOOST_ASIO_MOVE_ARG(T) t,
278 BOOST_ASIO_MOVE_ARG(Property) p) const
279 BOOST_ASIO_NOEXCEPT_IF((
280 call_traits<impl, T, void(Property)>::is_noexcept))
282 return require_concept(
283 BOOST_ASIO_MOVE_CAST(T)(t),
284 BOOST_ASIO_MOVE_CAST(Property)(p));
288 template <typename T = impl>
289 struct static_instance
291 static const T instance;
294 template <typename T>
295 const T static_instance<T>::instance = {};
297 } // namespace boost_asio_require_concept_fn
302 static BOOST_ASIO_CONSTEXPR const boost_asio_require_concept_fn::impl&
303 require_concept = boost_asio_require_concept_fn::static_instance<>::instance;
307 typedef boost_asio_require_concept_fn::impl require_concept_t;
309 template <typename T, typename Property>
310 struct can_require_concept :
311 integral_constant<bool,
312 boost_asio_require_concept_fn::call_traits<
313 require_concept_t, T, void(Property)>::overload !=
314 boost_asio_require_concept_fn::ill_formed>
318 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
320 template <typename T, typename Property>
321 constexpr bool can_require_concept_v
322 = can_require_concept<T, Property>::value;
324 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
326 template <typename T, typename Property>
327 struct is_nothrow_require_concept :
328 integral_constant<bool,
329 boost_asio_require_concept_fn::call_traits<
330 require_concept_t, T, void(Property)>::is_noexcept>
334 #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
336 template <typename T, typename Property>
337 constexpr bool is_nothrow_require_concept_v
338 = is_nothrow_require_concept<T, Property>::value;
340 #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
342 template <typename T, typename Property>
343 struct require_concept_result
345 typedef typename boost_asio_require_concept_fn::call_traits<
346 require_concept_t, T, void(Property)>::result_type type;
352 #endif // defined(GENERATING_DOCUMENTATION)
354 #include <boost/asio/detail/pop_options.hpp>
356 #endif // BOOST_ASIO_REQUIRE_CONCEPT_HPP