1//
2// execution/prefer_only.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_EXECUTION_PREFER_ONLY_HPP
12#define BOOST_ASIO_EXECUTION_PREFER_ONLY_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/prefer.hpp>
22#include <boost/asio/query.hpp>
23#include <boost/asio/traits/static_query.hpp>
24
25#include <boost/asio/detail/push_options.hpp>
26
27namespace boost {
28namespace asio {
29
30#if defined(GENERATING_DOCUMENTATION)
31
32namespace execution {
33
34/// A property adapter that is used with the polymorphic executor wrapper
35/// to mark properties as preferable, but not requirable.
36template <typename Property>
37struct prefer_only
38{
39 /// The prefer_only adapter applies to the same types as the nested property.
40 template <typename T>
41 static constexpr bool is_applicable_property_v =
42 is_applicable_property<T, Property>::value;
43
44 /// The context_t property cannot be required.
45 static constexpr bool is_requirable = false;
46
47 /// The context_t property can be preferred, it the underlying property can
48 /// be preferred.
49 /**
50 * @c true if @c Property::is_preferable is @c true, otherwise @c false.
51 */
52 static constexpr bool is_preferable = automatically_determined;
53
54 /// The type returned by queries against an @c any_executor.
55 typedef typename Property::polymorphic_query_result_type
56 polymorphic_query_result_type;
57};
58
59} // namespace execution
60
61#else // defined(GENERATING_DOCUMENTATION)
62
63namespace execution {
64namespace detail {
65
66template <typename InnerProperty, typename = void>
67struct prefer_only_is_preferable
68{
69 static constexpr bool is_preferable = false;
70};
71
72template <typename InnerProperty>
73struct prefer_only_is_preferable<InnerProperty,
74 enable_if_t<
75 InnerProperty::is_preferable
76 >
77 >
78{
79 static constexpr bool is_preferable = true;
80};
81
82template <typename InnerProperty, typename = void>
83struct prefer_only_polymorphic_query_result_type
84{
85};
86
87template <typename InnerProperty>
88struct prefer_only_polymorphic_query_result_type<InnerProperty,
89 void_t<
90 typename InnerProperty::polymorphic_query_result_type
91 >
92 >
93{
94 typedef typename InnerProperty::polymorphic_query_result_type
95 polymorphic_query_result_type;
96};
97
98template <typename InnerProperty, typename = void>
99struct prefer_only_property
100{
101 InnerProperty property;
102
103 prefer_only_property(const InnerProperty& p)
104 : property(p)
105 {
106 }
107};
108
109#if defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
110
111template <typename InnerProperty>
112struct prefer_only_property<InnerProperty,
113 void_t<
114 decltype(boost::asio::declval<const InnerProperty>().value())
115 >
116 >
117{
118 InnerProperty property;
119
120 prefer_only_property(const InnerProperty& p)
121 : property(p)
122 {
123 }
124
125 constexpr auto value() const
126 noexcept(noexcept(boost::asio::declval<const InnerProperty>().value()))
127 -> decltype(boost::asio::declval<const InnerProperty>().value())
128 {
129 return property.value();
130 }
131};
132
133#else // defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
134
135struct prefer_only_memfns_base
136{
137 void value();
138};
139
140template <typename T>
141struct prefer_only_memfns_derived
142 : T, prefer_only_memfns_base
143{
144};
145
146template <typename T, T>
147struct prefer_only_memfns_check
148{
149};
150
151template <typename>
152char (&prefer_only_value_memfn_helper(...))[2];
153
154template <typename T>
155char prefer_only_value_memfn_helper(
156 prefer_only_memfns_check<
157 void (prefer_only_memfns_base::*)(),
158 &prefer_only_memfns_derived<T>::value>*);
159
160template <typename InnerProperty>
161struct prefer_only_property<InnerProperty,
162 enable_if_t<
163 sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1
164 && !is_same<typename InnerProperty::polymorphic_query_result_type,
165 void>::value
166 >
167 >
168{
169 InnerProperty property;
170
171 prefer_only_property(const InnerProperty& p)
172 : property(p)
173 {
174 }
175
176 constexpr typename InnerProperty::polymorphic_query_result_type
177 value() const
178 {
179 return property.value();
180 }
181};
182
183#endif // defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
184
185} // namespace detail
186
187template <typename InnerProperty>
188struct prefer_only :
189 detail::prefer_only_is_preferable<InnerProperty>,
190 detail::prefer_only_polymorphic_query_result_type<InnerProperty>,
191 detail::prefer_only_property<InnerProperty>
192{
193 static constexpr bool is_requirable = false;
194
195 constexpr prefer_only(const InnerProperty& p)
196 : detail::prefer_only_property<InnerProperty>(p)
197 {
198 }
199
200#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
201 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
202 template <typename T>
203 static constexpr
204 typename traits::static_query<T, InnerProperty>::result_type
205 static_query()
206 noexcept(traits::static_query<T, InnerProperty>::is_noexcept)
207 {
208 return traits::static_query<T, InnerProperty>::value();
209 }
210
211 template <typename E, typename T = decltype(prefer_only::static_query<E>())>
212 static constexpr const T static_query_v
213 = prefer_only::static_query<E>();
214#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
215 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
216
217 template <typename Executor, typename Property>
218 friend constexpr
219 prefer_result_t<const Executor&, const InnerProperty&>
220 prefer(const Executor& ex, const prefer_only<Property>& p,
221 enable_if_t<
222 is_same<Property, InnerProperty>::value
223 >* = 0,
224 enable_if_t<
225 can_prefer<const Executor&, const InnerProperty&>::value
226 >* = 0)
227#if !defined(BOOST_ASIO_MSVC) \
228 && !defined(__clang__) // Clang crashes if noexcept is used here.
229 noexcept(is_nothrow_prefer<const Executor&, const InnerProperty&>::value)
230#endif // !defined(BOOST_ASIO_MSVC)
231 // && !defined(__clang__)
232 {
233 return boost::asio::prefer(ex, p.property);
234 }
235
236 template <typename Executor, typename Property>
237 friend constexpr
238 query_result_t<const Executor&, const InnerProperty&>
239 query(const Executor& ex, const prefer_only<Property>& p,
240 enable_if_t<
241 is_same<Property, InnerProperty>::value
242 >* = 0,
243 enable_if_t<
244 can_query<const Executor&, const InnerProperty&>::value
245 >* = 0)
246#if !defined(BOOST_ASIO_MSVC) \
247 && !defined(__clang__) // Clang crashes if noexcept is used here.
248 noexcept(is_nothrow_query<const Executor&, const InnerProperty&>::value)
249#endif // !defined(BOOST_ASIO_MSVC)
250 // && !defined(__clang__)
251 {
252 return boost::asio::query(ex, p.property);
253 }
254};
255
256#if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
257 && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
258template <typename InnerProperty> template <typename E, typename T>
259const T prefer_only<InnerProperty>::static_query_v;
260#endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
261 // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
262
263} // namespace execution
264
265template <typename T, typename InnerProperty>
266struct is_applicable_property<T, execution::prefer_only<InnerProperty>>
267 : is_applicable_property<T, InnerProperty>
268{
269};
270
271namespace traits {
272
273#if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
274 || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
275
276template <typename T, typename InnerProperty>
277struct static_query<T, execution::prefer_only<InnerProperty>> :
278 static_query<T, const InnerProperty&>
279{
280};
281
282#endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
283 // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
284
285#if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
286
287template <typename T, typename InnerProperty>
288struct prefer_free_default<T, execution::prefer_only<InnerProperty>,
289 enable_if_t<
290 can_prefer<const T&, const InnerProperty&>::value
291 >
292 >
293{
294 static constexpr bool is_valid = true;
295 static constexpr bool is_noexcept =
296 is_nothrow_prefer<const T&, const InnerProperty&>::value;
297
298 typedef prefer_result_t<const T&, const InnerProperty&> result_type;
299};
300
301#endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
302
303#if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
304
305template <typename T, typename InnerProperty>
306struct query_free<T, execution::prefer_only<InnerProperty>,
307 enable_if_t<
308 can_query<const T&, const InnerProperty&>::value
309 >
310 >
311{
312 static constexpr bool is_valid = true;
313 static constexpr bool is_noexcept =
314 is_nothrow_query<const T&, const InnerProperty&>::value;
315
316 typedef query_result_t<const T&, const InnerProperty&> result_type;
317};
318
319#endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
320
321} // namespace traits
322
323#endif // defined(GENERATING_DOCUMENTATION)
324
325} // namespace asio
326} // namespace boost
327
328#include <boost/asio/detail/pop_options.hpp>
329
330#endif // BOOST_ASIO_EXECUTION_PREFER_ONLY_HPP
331

source code of boost/libs/asio/include/boost/asio/execution/prefer_only.hpp