1 //
2 // execution/any_executor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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_ANY_EXECUTOR_HPP
12 #define BOOST_ASIO_EXECUTION_ANY_EXECUTOR_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 <new>
20 #include <typeinfo>
21 #include <boost/asio/detail/assert.hpp>
22 #include <boost/asio/detail/cstddef.hpp>
23 #include <boost/asio/detail/executor_function.hpp>
24 #include <boost/asio/detail/memory.hpp>
25 #include <boost/asio/detail/non_const_lvalue.hpp>
26 #include <boost/asio/detail/scoped_ptr.hpp>
27 #include <boost/asio/detail/type_traits.hpp>
28 #include <boost/asio/detail/throw_exception.hpp>
29 #include <boost/asio/detail/variadic_templates.hpp>
30 #include <boost/asio/execution/bad_executor.hpp>
31 #include <boost/asio/execution/blocking.hpp>
32 #include <boost/asio/execution/execute.hpp>
33 #include <boost/asio/execution/executor.hpp>
34 #include <boost/asio/prefer.hpp>
35 #include <boost/asio/query.hpp>
36 #include <boost/asio/require.hpp>
37 
38 #include <boost/asio/detail/push_options.hpp>
39 
40 namespace boost {
41 namespace asio {
42 
43 #if defined(GENERATING_DOCUMENTATION)
44 
45 namespace execution {
46 
47 /// Polymorphic executor wrapper.
48 template <typename... SupportableProperties>
49 class any_executor
50 {
51 public:
52   /// Default constructor.
53   any_executor() noexcept;
54 
55   /// Construct in an empty state. Equivalent effects to default constructor.
56   any_executor(nullptr_t) noexcept;
57 
58   /// Copy constructor.
59   any_executor(const any_executor& e) noexcept;
60 
61   /// Move constructor.
62   any_executor(any_executor&& e) noexcept;
63 
64   /// Construct to point to the same target as another any_executor.
65   template <class... OtherSupportableProperties>
66     any_executor(any_executor<OtherSupportableProperties...> e);
67 
68   /// Construct a polymorphic wrapper for the specified executor.
69   template <typename Executor>
70   any_executor(Executor e);
71 
72   /// Assignment operator.
73   any_executor& operator=(const any_executor& e) noexcept;
74 
75   /// Move assignment operator.
76   any_executor& operator=(any_executor&& e) noexcept;
77 
78   /// Assignment operator that sets the polymorphic wrapper to the empty state.
79   any_executor& operator=(nullptr_t);
80 
81   /// Assignment operator to create a polymorphic wrapper for the specified
82   /// executor.
83   template <typename Executor>
84   any_executor& operator=(Executor e);
85 
86   /// Destructor.
87   ~any_executor();
88 
89   /// Swap targets with another polymorphic wrapper.
90   void swap(any_executor& other) noexcept;
91 
92   /// Obtain a polymorphic wrapper with the specified property.
93   /**
94    * Do not call this function directly. It is intended for use with the
95    * boost::asio::require and boost::asio::prefer customisation points.
96    *
97    * For example:
98    * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
99    * auto ex2 = boost::asio::requre(ex, execution::blocking.possibly); @endcode
100    */
101   template <typename Property>
102   any_executor require(Property) const;
103 
104   /// Obtain a polymorphic wrapper with the specified property.
105   /**
106    * Do not call this function directly. It is intended for use with the
107    * boost::asio::prefer customisation point.
108    *
109    * For example:
110    * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...;
111    * auto ex2 = boost::asio::prefer(ex, execution::blocking.possibly); @endcode
112    */
113   template <typename Property>
114   any_executor prefer(Property) const;
115 
116   /// Obtain the value associated with the specified property.
117   /**
118    * Do not call this function directly. It is intended for use with the
119    * boost::asio::query customisation point.
120    *
121    * For example:
122    * @code execution::any_executor<execution::occupancy_t> ex = ...;
123    * size_t n = boost::asio::query(ex, execution::occupancy); @endcode
124    */
125   template <typename Property>
126   typename Property::polymorphic_query_result_type query(Property) const;
127 
128   /// Execute the function on the target executor.
129   /**
130    * Do not call this function directly. It is intended for use with the
131    * execution::execute customisation point.
132    *
133    * For example:
134    * @code execution::any_executor<> ex = ...;
135    * execution::execute(ex, my_function_object); @endcode
136    *
137    * Throws boost::asio::bad_executor if the polymorphic wrapper has no target.
138    */
139   template <typename Function>
140   void execute(Function&& f) const;
141 
142   /// Obtain the underlying execution context.
143   /**
144    * This function is provided for backward compatibility. It is automatically
145    * defined when the @c SupportableProperties... list includes a property of
146    * type <tt>execution::context_as<U></tt>, for some type <tt>U</tt>.
147    */
148   automatically_determined context() const;
149 
150   /// Determine whether the wrapper has a target executor.
151   /**
152    * @returns @c true if the polymorphic wrapper has a target executor,
153    * otherwise false.
154    */
155   explicit operator bool() const noexcept;
156 
157   /// Get the type of the target executor.
158   const type_info& target_type() const noexcept;
159 
160   /// Get a pointer to the target executor.
161   template <typename Executor> Executor* target() noexcept;
162 
163   /// Get a pointer to the target executor.
164   template <typename Executor> const Executor* target() const noexcept;
165 };
166 
167 /// Equality operator.
168 /**
169  * @relates any_executor
170  */
171 template <typename... SupportableProperties>
172 bool operator==(const any_executor<SupportableProperties...>& a,
173     const any_executor<SupportableProperties...>& b) noexcept;
174 
175 /// Equality operator.
176 /**
177  * @relates any_executor
178  */
179 template <typename... SupportableProperties>
180 bool operator==(const any_executor<SupportableProperties...>& a,
181     nullptr_t) noexcept;
182 
183 /// Equality operator.
184 /**
185  * @relates any_executor
186  */
187 template <typename... SupportableProperties>
188 bool operator==(nullptr_t,
189     const any_executor<SupportableProperties...>& b) noexcept;
190 
191 /// Inequality operator.
192 /**
193  * @relates any_executor
194  */
195 template <typename... SupportableProperties>
196 bool operator!=(const any_executor<SupportableProperties...>& a,
197     const any_executor<SupportableProperties...>& b) noexcept;
198 
199 /// Inequality operator.
200 /**
201  * @relates any_executor
202  */
203 template <typename... SupportableProperties>
204 bool operator!=(const any_executor<SupportableProperties...>& a,
205     nullptr_t) noexcept;
206 
207 /// Inequality operator.
208 /**
209  * @relates any_executor
210  */
211 template <typename... SupportableProperties>
212 bool operator!=(nullptr_t,
213     const any_executor<SupportableProperties...>& b) noexcept;
214 
215 } // namespace execution
216 
217 #else // defined(GENERATING_DOCUMENTATION)
218 
219 namespace execution {
220 
221 #if !defined(BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
222 #define BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL
223 
224 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
225 
226 template <typename... SupportableProperties>
227 class any_executor;
228 
229 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
230 
231 template <typename = void, typename = void, typename = void,
232     typename = void, typename = void, typename = void,
233     typename = void, typename = void, typename = void>
234 class any_executor;
235 
236 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
237 
238 #endif // !defined(BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
239 
240 template <typename U>
241 struct context_as_t;
242 
243 namespace detail {
244 
245 // Traits used to detect whether a property is requirable or preferable, taking
246 // into account that T::is_requirable or T::is_preferable may not not be well
247 // formed.
248 
249 template <typename T, typename = void>
250 struct is_requirable : false_type {};
251 
252 template <typename T>
253 struct is_requirable<T, typename enable_if<T::is_requirable>::type> :
254   true_type {};
255 
256 template <typename T, typename = void>
257 struct is_preferable : false_type {};
258 
259 template <typename T>
260 struct is_preferable<T, typename enable_if<T::is_preferable>::type> :
261   true_type {};
262 
263 // Trait used to detect context_as property, for backward compatibility.
264 
265 template <typename T>
266 struct is_context_as : false_type {};
267 
268 template <typename U>
269 struct is_context_as<context_as_t<U> > : true_type {};
270 
271 // Helper template to:
272 // - Check if a target can supply the supportable properties.
273 // - Find the first convertible-from-T property in the list.
274 
275 template <std::size_t I, typename Props>
276 struct supportable_properties;
277 
278 template <std::size_t I, typename Prop>
279 struct supportable_properties<I, void(Prop)>
280 {
281   template <typename T>
282   struct is_valid_target : integral_constant<bool,
283       (
284         is_requirable<Prop>::value
285           ? can_require<T, Prop>::value
286           : true
287       )
288       &&
289       (
290         is_preferable<Prop>::value
291           ? can_prefer<T, Prop>::value
292           : true
293       )
294       &&
295       (
296         !is_requirable<Prop>::value && !is_preferable<Prop>::value
297           ? can_query<T, Prop>::value
298           : true
299       )
300     >
301   {
302   };
303 
304   struct found
305   {
306     BOOST_ASIO_STATIC_CONSTEXPR(bool, value = true);
307     typedef Prop type;
308     typedef typename Prop::polymorphic_query_result_type query_result_type;
309     BOOST_ASIO_STATIC_CONSTEXPR(std::size_t, index = I);
310   };
311 
312   struct not_found
313   {
314     BOOST_ASIO_STATIC_CONSTEXPR(bool, value = false);
315   };
316 
317   template <typename T>
318   struct find_convertible_property :
319       conditional<
320         is_same<T, Prop>::value || is_convertible<T, Prop>::value,
321         found,
322         not_found
323       >::type {};
324 
325   template <typename T>
326   struct find_convertible_requirable_property :
327       conditional<
328         is_requirable<Prop>::value
329           && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
330         found,
331         not_found
332       >::type {};
333 
334   template <typename T>
335   struct find_convertible_preferable_property :
336       conditional<
337         is_preferable<Prop>::value
338           && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),
339         found,
340         not_found
341       >::type {};
342 
343   struct find_context_as_property :
344       conditional<
345         is_context_as<Prop>::value,
346         found,
347         not_found
348       >::type {};
349 };
350 
351 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
352 
353 template <std::size_t I, typename Head, typename... Tail>
354 struct supportable_properties<I, void(Head, Tail...)>
355 {
356   template <typename T>
357   struct is_valid_target : integral_constant<bool,
358       (
359         supportable_properties<I,
360           void(Head)>::template is_valid_target<T>::value
361         &&
362         supportable_properties<I + 1,
363           void(Tail...)>::template is_valid_target<T>::value
364       )
365     >
366   {
367   };
368 
369   template <typename T>
370   struct find_convertible_property :
371       conditional<
372         is_convertible<T, Head>::value,
373         typename supportable_properties<I, void(Head)>::found,
374         typename supportable_properties<I + 1,
375             void(Tail...)>::template find_convertible_property<T>
376       >::type {};
377 
378   template <typename T>
379   struct find_convertible_requirable_property :
380       conditional<
381         is_requirable<Head>::value
382           && is_convertible<T, Head>::value,
383         typename supportable_properties<I, void(Head)>::found,
384         typename supportable_properties<I + 1,
385             void(Tail...)>::template find_convertible_requirable_property<T>
386       >::type {};
387 
388   template <typename T>
389   struct find_convertible_preferable_property :
390       conditional<
391         is_preferable<Head>::value
392           && is_convertible<T, Head>::value,
393         typename supportable_properties<I, void(Head)>::found,
394         typename supportable_properties<I + 1,
395             void(Tail...)>::template find_convertible_preferable_property<T>
396       >::type {};
397 
398   struct find_context_as_property :
399       conditional<
400         is_context_as<Head>::value,
401         typename supportable_properties<I, void(Head)>::found,
402         typename supportable_properties<I + 1,
403             void(Tail...)>::find_context_as_property
404       >::type {};
405 };
406 
407 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
408 
409 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \
410   template <std::size_t I, \
411     typename Head, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
412   struct supportable_properties<I, \
413       void(Head, BOOST_ASIO_VARIADIC_TARGS(n))> \
414   { \
415     template <typename T> \
416     struct is_valid_target : integral_constant<bool, \
417         ( \
418           supportable_properties<I, \
419             void(Head)>::template is_valid_target<T>::value \
420           && \
421           supportable_properties<I + 1, \
422               void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
423                 is_valid_target<T>::value \
424         ) \
425       > \
426     { \
427     }; \
428   \
429     template <typename T> \
430     struct find_convertible_property : \
431         conditional< \
432           is_convertible<T, Head>::value, \
433           typename supportable_properties<I, void(Head)>::found, \
434           typename supportable_properties<I + 1, \
435               void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
436                 find_convertible_property<T> \
437         >::type {}; \
438   \
439     template <typename T> \
440     struct find_convertible_requirable_property : \
441         conditional< \
442           is_requirable<Head>::value \
443             && is_convertible<T, Head>::value, \
444           typename supportable_properties<I, void(Head)>::found, \
445           typename supportable_properties<I + 1, \
446               void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
447                 find_convertible_requirable_property<T> \
448         >::type {}; \
449   \
450     template <typename T> \
451     struct find_convertible_preferable_property : \
452         conditional< \
453           is_preferable<Head>::value \
454             && is_convertible<T, Head>::value, \
455           typename supportable_properties<I, void(Head)>::found, \
456           typename supportable_properties<I + 1, \
457               void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
458                 find_convertible_preferable_property<T> \
459         >::type {}; \
460   \
461     struct find_context_as_property : \
462         conditional< \
463           is_context_as<Head>::value, \
464           typename supportable_properties<I, void(Head)>::found, \
465           typename supportable_properties<I + 1, void( \
466             BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property \
467         >::type {}; \
468   }; \
469   /**/
470 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF)
471 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF
472 
473 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
474 
475 template <typename T, typename Props>
476 struct is_valid_target_executor :
477   conditional<
478     is_executor<T>::value,
479     typename supportable_properties<0, Props>::template is_valid_target<T>,
480     false_type
481   >::type
482 {
483 };
484 
485 class any_executor_base
486 {
487 public:
488   any_executor_base() BOOST_ASIO_NOEXCEPT
489     : object_fns_(object_fns_table<void>()),
490       target_(0),
491       target_fns_(target_fns_table<void>())
492   {
493   }
494 
495   template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
496   any_executor_base(Executor ex, false_type)
497     : target_fns_(target_fns_table<Executor>(
498           any_executor_base::query_blocking(ex,
499             can_query<const Executor&, const execution::blocking_t&>())
500           == execution::blocking.always))
501   {
502     any_executor_base::construct_object(ex,
503         integral_constant<bool,
504           sizeof(Executor) <= sizeof(object_type)
505             && alignment_of<Executor>::value <= alignment_of<object_type>::value
506         >());
507   }
508 
509   template <BOOST_ASIO_EXECUTION_EXECUTOR Executor>
510   any_executor_base(Executor other, true_type)
511     : object_fns_(object_fns_table<boost::asio::detail::shared_ptr<void> >()),
512       target_fns_(other.target_fns_)
513   {
514     boost::asio::detail::shared_ptr<Executor> p =
515       boost::asio::detail::make_shared<Executor>(
516           BOOST_ASIO_MOVE_CAST(Executor)(other));
517     target_ = p->template target<void>();
518     new (&object_) boost::asio::detail::shared_ptr<void>(
519         BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p));
520   }
521 
522   any_executor_base(const any_executor_base& other) BOOST_ASIO_NOEXCEPT
523     : object_fns_(other.object_fns_),
524       target_fns_(other.target_fns_)
525   {
526     object_fns_->copy(*this, other);
527   }
528 
529   ~any_executor_base() BOOST_ASIO_NOEXCEPT
530   {
531     object_fns_->destroy(*this);
532   }
533 
534   any_executor_base& operator=(
535       const any_executor_base& other) BOOST_ASIO_NOEXCEPT
536   {
537     if (this != &other)
538     {
539       object_fns_->destroy(*this);
540       object_fns_ = other.object_fns_;
541       target_fns_ = other.target_fns_;
542       object_fns_->copy(*this, other);
543     }
544     return *this;
545   }
546 
547   any_executor_base& operator=(nullptr_t) BOOST_ASIO_NOEXCEPT
548   {
549     object_fns_->destroy(*this);
550     target_ = 0;
551     object_fns_ = object_fns_table<void>();
552     target_fns_ = target_fns_table<void>();
553     return *this;
554   }
555 
556 #if defined(BOOST_ASIO_HAS_MOVE)
557 
558   any_executor_base(any_executor_base&& other) BOOST_ASIO_NOEXCEPT
559     : object_fns_(other.object_fns_),
560       target_fns_(other.target_fns_)
561   {
562     other.object_fns_ = object_fns_table<void>();
563     other.target_fns_ = target_fns_table<void>();
564     object_fns_->move(*this, other);
565     other.target_ = 0;
566   }
567 
568   any_executor_base& operator=(
569       any_executor_base&& other) BOOST_ASIO_NOEXCEPT
570   {
571     if (this != &other)
572     {
573       object_fns_->destroy(*this);
574       object_fns_ = other.object_fns_;
575       other.object_fns_ = object_fns_table<void>();
576       target_fns_ = other.target_fns_;
577       other.target_fns_ = target_fns_table<void>();
578       object_fns_->move(*this, other);
579       other.target_ = 0;
580     }
581     return *this;
582   }
583 
584 #endif // defined(BOOST_ASIO_HAS_MOVE)
585 
586   void swap(any_executor_base& other) BOOST_ASIO_NOEXCEPT
587   {
588     if (this != &other)
589     {
590       any_executor_base tmp(BOOST_ASIO_MOVE_CAST(any_executor_base)(other));
591       other = BOOST_ASIO_MOVE_CAST(any_executor_base)(*this);
592       *this = BOOST_ASIO_MOVE_CAST(any_executor_base)(tmp);
593     }
594   }
595 
596   template <typename F>
597   void execute(BOOST_ASIO_MOVE_ARG(F) f) const
598   {
599     if (target_fns_->blocking_execute != 0)
600     {
601       boost::asio::detail::non_const_lvalue<F> f2(f);
602       target_fns_->blocking_execute(*this, function_view(f2.value));
603     }
604     else
605     {
606       target_fns_->execute(*this,
607           function(BOOST_ASIO_MOVE_CAST(F)(f), std::allocator<void>()));
608     }
609   }
610 
611   template <typename Executor>
612   Executor* target()
613   {
614     return static_cast<Executor*>(target_);
615   }
616 
617   template <typename Executor>
618   const Executor* target() const
619   {
620     return static_cast<Executor*>(target_);
621   }
622 
623 #if !defined(BOOST_ASIO_NO_TYPEID)
624   const std::type_info& target_type() const
625 #else // !defined(BOOST_ASIO_NO_TYPEID)
626   const void* target_type() const
627 #endif // !defined(BOOST_ASIO_NO_TYPEID)
628   {
629     return target_fns_->target_type();
630   }
631 
632   struct unspecified_bool_type_t {};
633   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
634   static void unspecified_bool_true(unspecified_bool_type_t) {}
635 
636   operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
637   {
638     return target_ ? &any_executor_base::unspecified_bool_true : 0;
639   }
640 
641   bool operator!() const BOOST_ASIO_NOEXCEPT
642   {
643     return target_ == 0;
644   }
645 
646 protected:
647   bool equality_helper(const any_executor_base& other) const BOOST_ASIO_NOEXCEPT
648   {
649     if (target_ == other.target_)
650       return true;
651     if (target_ && !other.target_)
652       return false;
653     if (!target_ && other.target_)
654       return false;
655     if (target_fns_ != other.target_fns_)
656       return false;
657     return target_fns_->equal(*this, other);
658   }
659 
660   template <typename Ex>
661   Ex& object()
662   {
663     return *static_cast<Ex*>(static_cast<void*>(&object_));
664   }
665 
666   template <typename Ex>
667   const Ex& object() const
668   {
669     return *static_cast<const Ex*>(static_cast<const void*>(&object_));
670   }
671 
672   struct object_fns
673   {
674     void (*destroy)(any_executor_base&);
675     void (*copy)(any_executor_base&, const any_executor_base&);
676     void (*move)(any_executor_base&, any_executor_base&);
677     const void* (*target)(const any_executor_base&);
678   };
679 
680   static void destroy_void(any_executor_base&)
681   {
682   }
683 
684   static void copy_void(any_executor_base& ex1, const any_executor_base&)
685   {
686     ex1.target_ = 0;
687   }
688 
689   static void move_void(any_executor_base& ex1, any_executor_base&)
690   {
691     ex1.target_ = 0;
692   }
693 
694   static const void* target_void(const any_executor_base&)
695   {
696     return 0;
697   }
698 
699   template <typename Obj>
700   static const object_fns* object_fns_table(
701       typename enable_if<
702         is_same<Obj, void>::value
703       >::type* = 0)
704   {
705     static const object_fns fns =
706     {
707       &any_executor_base::destroy_void,
708       &any_executor_base::copy_void,
709       &any_executor_base::move_void,
710       &any_executor_base::target_void
711     };
712     return &fns;
713   }
714 
715   static void destroy_shared(any_executor_base& ex)
716   {
717     typedef boost::asio::detail::shared_ptr<void> type;
718     ex.object<type>().~type();
719   }
720 
721   static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)
722   {
723     typedef boost::asio::detail::shared_ptr<void> type;
724     new (&ex1.object_) type(ex2.object<type>());
725     ex1.target_ = ex2.target_;
726   }
727 
728   static void move_shared(any_executor_base& ex1, any_executor_base& ex2)
729   {
730     typedef boost::asio::detail::shared_ptr<void> type;
731     new (&ex1.object_) type(BOOST_ASIO_MOVE_CAST(type)(ex2.object<type>()));
732     ex1.target_ = ex2.target_;
733     ex2.object<type>().~type();
734   }
735 
736   static const void* target_shared(const any_executor_base& ex)
737   {
738     typedef boost::asio::detail::shared_ptr<void> type;
739     return ex.object<type>().get();
740   }
741 
742   template <typename Obj>
743   static const object_fns* object_fns_table(
744       typename enable_if<
745         is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
746       >::type* = 0)
747   {
748     static const object_fns fns =
749     {
750       &any_executor_base::destroy_shared,
751       &any_executor_base::copy_shared,
752       &any_executor_base::move_shared,
753       &any_executor_base::target_shared
754     };
755     return &fns;
756   }
757 
758   template <typename Obj>
759   static void destroy_object(any_executor_base& ex)
760   {
761     ex.object<Obj>().~Obj();
762   }
763 
764   template <typename Obj>
765   static void copy_object(any_executor_base& ex1, const any_executor_base& ex2)
766   {
767     new (&ex1.object_) Obj(ex2.object<Obj>());
768     ex1.target_ = &ex1.object<Obj>();
769   }
770 
771   template <typename Obj>
772   static void move_object(any_executor_base& ex1, any_executor_base& ex2)
773   {
774     new (&ex1.object_) Obj(BOOST_ASIO_MOVE_CAST(Obj)(ex2.object<Obj>()));
775     ex1.target_ = &ex1.object<Obj>();
776     ex2.object<Obj>().~Obj();
777   }
778 
779   template <typename Obj>
780   static const void* target_object(const any_executor_base& ex)
781   {
782     return &ex.object<Obj>();
783   }
784 
785   template <typename Obj>
786   static const object_fns* object_fns_table(
787       typename enable_if<
788         !is_same<Obj, void>::value
789           && !is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
790       >::type* = 0)
791   {
792     static const object_fns fns =
793     {
794       &any_executor_base::destroy_object<Obj>,
795       &any_executor_base::copy_object<Obj>,
796       &any_executor_base::move_object<Obj>,
797       &any_executor_base::target_object<Obj>
798     };
799     return &fns;
800   }
801 
802   typedef boost::asio::detail::executor_function function;
803   typedef boost::asio::detail::executor_function_view function_view;
804 
805   struct target_fns
806   {
807 #if !defined(BOOST_ASIO_NO_TYPEID)
808     const std::type_info& (*target_type)();
809 #else // !defined(BOOST_ASIO_NO_TYPEID)
810     const void* (*target_type)();
811 #endif // !defined(BOOST_ASIO_NO_TYPEID)
812     bool (*equal)(const any_executor_base&, const any_executor_base&);
813     void (*execute)(const any_executor_base&, BOOST_ASIO_MOVE_ARG(function));
814     void (*blocking_execute)(const any_executor_base&, function_view);
815   };
816 
817 #if !defined(BOOST_ASIO_NO_TYPEID)
818   static const std::type_info& target_type_void()
819   {
820     return typeid(void);
821   }
822 #else // !defined(BOOST_ASIO_NO_TYPEID)
823   static const void* target_type_void()
824   {
825     return 0;
826   }
827 #endif // !defined(BOOST_ASIO_NO_TYPEID)
828 
829   static bool equal_void(const any_executor_base&, const any_executor_base&)
830   {
831     return true;
832   }
833 
834   static void execute_void(const any_executor_base&,
835       BOOST_ASIO_MOVE_ARG(function))
836   {
837     bad_executor ex;
838     boost::asio::detail::throw_exception(ex);
839   }
840 
841   static void blocking_execute_void(const any_executor_base&, function_view)
842   {
843     bad_executor ex;
844     boost::asio::detail::throw_exception(ex);
845   }
846 
847   template <typename Ex>
848   static const target_fns* target_fns_table(
849       typename enable_if<
850         is_same<Ex, void>::value
851       >::type* = 0)
852   {
853     static const target_fns fns =
854     {
855       &any_executor_base::target_type_void,
856       &any_executor_base::equal_void,
857       &any_executor_base::execute_void,
858       &any_executor_base::blocking_execute_void
859     };
860     return &fns;
861   }
862 
863 #if !defined(BOOST_ASIO_NO_TYPEID)
864   template <typename Ex>
865   static const std::type_info& target_type_ex()
866   {
867     return typeid(Ex);
868   }
869 #else // !defined(BOOST_ASIO_NO_TYPEID)
870   template <typename Ex>
871   static const void* target_type_ex()
872   {
873     static int unique_id;
874     return &unique_id;
875   }
876 #endif // !defined(BOOST_ASIO_NO_TYPEID)
877 
878   template <typename Ex>
879   static bool equal_ex(const any_executor_base& ex1,
880       const any_executor_base& ex2)
881   {
882     return *ex1.target<Ex>() == *ex2.target<Ex>();
883   }
884 
885   template <typename Ex>
886   static void execute_ex(const any_executor_base& ex,
887       BOOST_ASIO_MOVE_ARG(function) f)
888   {
889     execution::execute(*ex.target<Ex>(), BOOST_ASIO_MOVE_CAST(function)(f));
890   }
891 
892   template <typename Ex>
893   static void blocking_execute_ex(const any_executor_base& ex, function_view f)
894   {
895     execution::execute(*ex.target<Ex>(), f);
896   }
897 
898   template <typename Ex>
899   static const target_fns* target_fns_table(bool is_always_blocking,
900       typename enable_if<
901         !is_same<Ex, void>::value
902       >::type* = 0)
903   {
904     static const target_fns fns_with_execute =
905     {
906       &any_executor_base::target_type_ex<Ex>,
907       &any_executor_base::equal_ex<Ex>,
908       &any_executor_base::execute_ex<Ex>,
909       0
910     };
911 
912     static const target_fns fns_with_blocking_execute =
913     {
914       &any_executor_base::target_type_ex<Ex>,
915       &any_executor_base::equal_ex<Ex>,
916       0,
917       &any_executor_base::blocking_execute_ex<Ex>
918     };
919 
920     return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute;
921   }
922 
923 #if defined(BOOST_ASIO_MSVC)
924 # pragma warning (push)
925 # pragma warning (disable:4702)
926 #endif // defined(BOOST_ASIO_MSVC)
927 
928   static void query_fn_void(void*, const void*, const void*)
929   {
930     bad_executor ex;
931     boost::asio::detail::throw_exception(ex);
932   }
933 
934   template <typename Ex, class Prop>
935   static void query_fn_non_void(void*, const void* ex, const void* prop,
936       typename enable_if<
937         boost::asio::can_query<const Ex&, const Prop&>::value
938           && is_same<typename Prop::polymorphic_query_result_type, void>::value
939       >::type*)
940   {
941     boost::asio::query(*static_cast<const Ex*>(ex),
942         *static_cast<const Prop*>(prop));
943   }
944 
945   template <typename Ex, class Prop>
946   static void query_fn_non_void(void*, const void*, const void*,
947       typename enable_if<
948         !boost::asio::can_query<const Ex&, const Prop&>::value
949           && is_same<typename Prop::polymorphic_query_result_type, void>::value
950       >::type*)
951   {
952   }
953 
954   template <typename Ex, class Prop>
955   static void query_fn_non_void(void* result, const void* ex, const void* prop,
956       typename enable_if<
957         boost::asio::can_query<const Ex&, const Prop&>::value
958           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
959           && is_reference<typename Prop::polymorphic_query_result_type>::value
960       >::type*)
961   {
962     *static_cast<typename remove_reference<
963       typename Prop::polymorphic_query_result_type>::type**>(result)
964         = &static_cast<typename Prop::polymorphic_query_result_type>(
965             boost::asio::query(*static_cast<const Ex*>(ex),
966               *static_cast<const Prop*>(prop)));
967   }
968 
969   template <typename Ex, class Prop>
970   static void query_fn_non_void(void*, const void*, const void*,
971       typename enable_if<
972         !boost::asio::can_query<const Ex&, const Prop&>::value
973           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
974           && is_reference<typename Prop::polymorphic_query_result_type>::value
975       >::type*)
976   {
977     std::terminate(); // Combination should not be possible.
978   }
979 
980   template <typename Ex, class Prop>
981   static void query_fn_non_void(void* result, const void* ex, const void* prop,
982       typename enable_if<
983         boost::asio::can_query<const Ex&, const Prop&>::value
984           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
985           && is_scalar<typename Prop::polymorphic_query_result_type>::value
986       >::type*)
987   {
988     *static_cast<typename Prop::polymorphic_query_result_type*>(result)
989       = static_cast<typename Prop::polymorphic_query_result_type>(
990           boost::asio::query(*static_cast<const Ex*>(ex),
991             *static_cast<const Prop*>(prop)));
992   }
993 
994   template <typename Ex, class Prop>
995   static void query_fn_non_void(void* result, const void*, const void*,
996       typename enable_if<
997         !boost::asio::can_query<const Ex&, const Prop&>::value
998           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
999           && is_scalar<typename Prop::polymorphic_query_result_type>::value
1000       >::type*)
1001   {
1002     *static_cast<typename Prop::polymorphic_query_result_type*>(result)
1003       = typename Prop::polymorphic_query_result_type();
1004   }
1005 
1006   template <typename Ex, class Prop>
1007   static void query_fn_non_void(void* result, const void* ex, const void* prop,
1008       typename enable_if<
1009         boost::asio::can_query<const Ex&, const Prop&>::value
1010           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
1011           && !is_reference<typename Prop::polymorphic_query_result_type>::value
1012           && !is_scalar<typename Prop::polymorphic_query_result_type>::value
1013       >::type*)
1014   {
1015     *static_cast<typename Prop::polymorphic_query_result_type**>(result)
1016       = new typename Prop::polymorphic_query_result_type(
1017           boost::asio::query(*static_cast<const Ex*>(ex),
1018             *static_cast<const Prop*>(prop)));
1019   }
1020 
1021   template <typename Ex, class Prop>
1022   static void query_fn_non_void(void* result, const void*, const void*, ...)
1023   {
1024     *static_cast<typename Prop::polymorphic_query_result_type**>(result)
1025       = new typename Prop::polymorphic_query_result_type();
1026   }
1027 
1028   template <typename Ex, class Prop>
1029   static void query_fn_impl(void* result, const void* ex, const void* prop,
1030       typename enable_if<
1031         is_same<Ex, void>::value
1032       >::type*)
1033   {
1034     query_fn_void(result, ex, prop);
1035   }
1036 
1037   template <typename Ex, class Prop>
1038   static void query_fn_impl(void* result, const void* ex, const void* prop,
1039       typename enable_if<
1040         !is_same<Ex, void>::value
1041       >::type*)
1042   {
1043     query_fn_non_void<Ex, Prop>(result, ex, prop, 0);
1044   }
1045 
1046   template <typename Ex, class Prop>
1047   static void query_fn(void* result, const void* ex, const void* prop)
1048   {
1049     query_fn_impl<Ex, Prop>(result, ex, prop, 0);
1050   }
1051 
1052   template <typename Poly, typename Ex, class Prop>
1053   static Poly require_fn_impl(const void*, const void*,
1054       typename enable_if<
1055         is_same<Ex, void>::value
1056       >::type*)
1057   {
1058     bad_executor ex;
1059     boost::asio::detail::throw_exception(ex);
1060     return Poly();
1061   }
1062 
1063   template <typename Poly, typename Ex, class Prop>
1064   static Poly require_fn_impl(const void* ex, const void* prop,
1065       typename enable_if<
1066         !is_same<Ex, void>::value && Prop::is_requirable
1067       >::type*)
1068   {
1069     return boost::asio::require(*static_cast<const Ex*>(ex),
1070         *static_cast<const Prop*>(prop));
1071   }
1072 
1073   template <typename Poly, typename Ex, class Prop>
1074   static Poly require_fn_impl(const void*, const void*, ...)
1075   {
1076     return Poly();
1077   }
1078 
1079   template <typename Poly, typename Ex, class Prop>
1080   static Poly require_fn(const void* ex, const void* prop)
1081   {
1082     return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1083   }
1084 
1085   template <typename Poly, typename Ex, class Prop>
1086   static Poly prefer_fn_impl(const void*, const void*,
1087       typename enable_if<
1088         is_same<Ex, void>::value
1089       >::type*)
1090   {
1091     bad_executor ex;
1092     boost::asio::detail::throw_exception(ex);
1093     return Poly();
1094   }
1095 
1096   template <typename Poly, typename Ex, class Prop>
1097   static Poly prefer_fn_impl(const void* ex, const void* prop,
1098       typename enable_if<
1099         !is_same<Ex, void>::value && Prop::is_preferable
1100       >::type*)
1101   {
1102     return boost::asio::prefer(*static_cast<const Ex*>(ex),
1103         *static_cast<const Prop*>(prop));
1104   }
1105 
1106   template <typename Poly, typename Ex, class Prop>
1107   static Poly prefer_fn_impl(const void*, const void*, ...)
1108   {
1109     return Poly();
1110   }
1111 
1112   template <typename Poly, typename Ex, class Prop>
1113   static Poly prefer_fn(const void* ex, const void* prop)
1114   {
1115     return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1116   }
1117 
1118   template <typename Poly>
1119   struct prop_fns
1120   {
1121     void (*query)(void*, const void*, const void*);
1122     Poly (*require)(const void*, const void*);
1123     Poly (*prefer)(const void*, const void*);
1124   };
1125 
1126 #if defined(BOOST_ASIO_MSVC)
1127 # pragma warning (pop)
1128 #endif // defined(BOOST_ASIO_MSVC)
1129 
1130 private:
1131   template <typename Executor>
1132   static execution::blocking_t query_blocking(const Executor& ex, true_type)
1133   {
1134     return boost::asio::query(ex, execution::blocking);
1135   }
1136 
1137   template <typename Executor>
1138   static execution::blocking_t query_blocking(const Executor&, false_type)
1139   {
1140     return execution::blocking_t();
1141   }
1142 
1143   template <typename Executor>
1144   void construct_object(Executor& ex, true_type)
1145   {
1146     object_fns_ = object_fns_table<Executor>();
1147     target_ = new (&object_) Executor(BOOST_ASIO_MOVE_CAST(Executor)(ex));
1148   }
1149 
1150   template <typename Executor>
1151   void construct_object(Executor& ex, false_type)
1152   {
1153     object_fns_ = object_fns_table<boost::asio::detail::shared_ptr<void> >();
1154     boost::asio::detail::shared_ptr<Executor> p =
1155       boost::asio::detail::make_shared<Executor>(
1156           BOOST_ASIO_MOVE_CAST(Executor)(ex));
1157     target_ = p.get();
1158     new (&object_) boost::asio::detail::shared_ptr<void>(
1159         BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p));
1160   }
1161 
1162 /*private:*/public:
1163 //  template <typename...> friend class any_executor;
1164 
1165   typedef aligned_storage<
1166       sizeof(boost::asio::detail::shared_ptr<void>),
1167       alignment_of<boost::asio::detail::shared_ptr<void> >::value
1168     >::type object_type;
1169 
1170   object_type object_;
1171   const object_fns* object_fns_;
1172   void* target_;
1173   const target_fns* target_fns_;
1174 };
1175 
1176 template <typename Derived, typename Property, typename = void>
1177 struct any_executor_context
1178 {
1179 };
1180 
1181 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1182 
1183 template <typename Derived, typename Property>
1184 struct any_executor_context<Derived, Property,
1185     typename enable_if<Property::value>::type>
1186 {
1187   typename Property::query_result_type context() const
1188   {
1189     return static_cast<const Derived*>(this)->query(typename Property::type());
1190   }
1191 };
1192 
1193 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1194 
1195 } // namespace detail
1196 
1197 template <>
1198 class any_executor<> : public detail::any_executor_base
1199 {
1200 public:
1201   any_executor() BOOST_ASIO_NOEXCEPT
1202     : detail::any_executor_base()
1203   {
1204   }
1205 
1206   any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1207     : detail::any_executor_base()
1208   {
1209   }
1210 
1211   template <typename Executor>
1212   any_executor(Executor ex,
1213       typename enable_if<
1214         conditional<
1215           !is_same<Executor, any_executor>::value
1216             && !is_base_of<detail::any_executor_base, Executor>::value,
1217           is_executor<Executor>,
1218           false_type
1219         >::type::value
1220       >::type* = 0)
1221     : detail::any_executor_base(
1222         BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type())
1223   {
1224   }
1225 
1226 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1227 
1228   template <typename... OtherSupportableProperties>
1229   any_executor(any_executor<OtherSupportableProperties...> other)
1230     : detail::any_executor_base(
1231         static_cast<const detail::any_executor_base&>(other))
1232   {
1233   }
1234 
1235 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1236 
1237   template <typename U0, typename U1, typename U2, typename U3,
1238       typename U4, typename U5, typename U6, typename U7>
1239   any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other)
1240     : detail::any_executor_base(
1241         static_cast<const detail::any_executor_base&>(other))
1242   {
1243   }
1244 
1245 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1246 
1247   any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1248     : detail::any_executor_base(
1249         static_cast<const detail::any_executor_base&>(other))
1250   {
1251   }
1252 
1253   any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1254   {
1255     if (this != &other)
1256     {
1257       detail::any_executor_base::operator=(
1258           static_cast<const detail::any_executor_base&>(other));
1259     }
1260     return *this;
1261   }
1262 
1263   any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1264   {
1265     detail::any_executor_base::operator=(p);
1266     return *this;
1267   }
1268 
1269 #if defined(BOOST_ASIO_HAS_MOVE)
1270 
1271   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1272     : detail::any_executor_base(
1273         static_cast<any_executor_base&&>(
1274           static_cast<any_executor_base&>(other)))
1275   {
1276   }
1277 
1278   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1279   {
1280     if (this != &other)
1281     {
1282       detail::any_executor_base::operator=(
1283           static_cast<detail::any_executor_base&&>(
1284             static_cast<detail::any_executor_base&>(other)));
1285     }
1286     return *this;
1287   }
1288 
1289 #endif // defined(BOOST_ASIO_HAS_MOVE)
1290 
1291   void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1292   {
1293     detail::any_executor_base::swap(
1294         static_cast<detail::any_executor_base&>(other));
1295   }
1296 
1297   using detail::any_executor_base::execute;
1298   using detail::any_executor_base::target;
1299   using detail::any_executor_base::target_type;
1300   using detail::any_executor_base::operator unspecified_bool_type;
1301   using detail::any_executor_base::operator!;
1302 
1303   bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1304   {
1305     return any_executor_base::equality_helper(other);
1306   }
1307 
1308   template <typename AnyExecutor1, typename AnyExecutor2>
1309   friend typename enable_if<
1310     is_same<AnyExecutor1, any_executor>::value
1311       || is_same<AnyExecutor2, any_executor>::value,
1312     bool
1313   >::type operator==(const AnyExecutor1& a,
1314       const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1315   {
1316     return static_cast<const any_executor&>(a).equality_helper(b);
1317   }
1318 
1319   template <typename AnyExecutor>
1320   friend typename enable_if<
1321     is_same<AnyExecutor, any_executor>::value,
1322     bool
1323   >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1324   {
1325     return !a;
1326   }
1327 
1328   template <typename AnyExecutor>
1329   friend typename enable_if<
1330     is_same<AnyExecutor, any_executor>::value,
1331     bool
1332   >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1333   {
1334     return !b;
1335   }
1336 
1337   template <typename AnyExecutor1, typename AnyExecutor2>
1338   friend typename enable_if<
1339     is_same<AnyExecutor1, any_executor>::value
1340       || is_same<AnyExecutor2, any_executor>::value,
1341     bool
1342   >::type operator!=(const AnyExecutor1& a,
1343       const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1344   {
1345     return !static_cast<const any_executor&>(a).equality_helper(b);
1346   }
1347 
1348   template <typename AnyExecutor>
1349   friend typename enable_if<
1350     is_same<AnyExecutor, any_executor>::value,
1351     bool
1352   >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1353   {
1354     return !!a;
1355   }
1356 
1357   template <typename AnyExecutor>
1358   friend typename enable_if<
1359     is_same<AnyExecutor, any_executor>::value,
1360     bool
1361   >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1362   {
1363     return !!b;
1364   }
1365 };
1366 
1367 inline void swap(any_executor<>& a, any_executor<>& b) BOOST_ASIO_NOEXCEPT
1368 {
1369   return a.swap(b);
1370 }
1371 
1372 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1373 
1374 template <typename... SupportableProperties>
1375 class any_executor :
1376   public detail::any_executor_base,
1377   public detail::any_executor_context<
1378     any_executor<SupportableProperties...>,
1379       typename detail::supportable_properties<
1380         0, void(SupportableProperties...)>::find_context_as_property>
1381 {
1382 public:
1383   any_executor() BOOST_ASIO_NOEXCEPT
1384     : detail::any_executor_base(),
1385       prop_fns_(prop_fns_table<void>())
1386   {
1387   }
1388 
1389   any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1390     : detail::any_executor_base(),
1391       prop_fns_(prop_fns_table<void>())
1392   {
1393   }
1394 
1395   template <typename Executor>
1396   any_executor(Executor ex,
1397       typename enable_if<
1398         conditional<
1399           !is_same<Executor, any_executor>::value
1400             && !is_base_of<detail::any_executor_base, Executor>::value,
1401           detail::is_valid_target_executor<
1402             Executor, void(SupportableProperties...)>,
1403           false_type
1404         >::type::value
1405       >::type* = 0)
1406     : detail::any_executor_base(
1407         BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type()),
1408       prop_fns_(prop_fns_table<Executor>())
1409   {
1410   }
1411 
1412   template <typename... OtherSupportableProperties>
1413   any_executor(any_executor<OtherSupportableProperties...> other,
1414       typename enable_if<
1415         conditional<
1416           !is_same<
1417             any_executor<OtherSupportableProperties...>,
1418             any_executor
1419           >::value,
1420           typename detail::supportable_properties<
1421             0, void(SupportableProperties...)>::template is_valid_target<
1422               any_executor<OtherSupportableProperties...> >,
1423           false_type
1424         >::type::value
1425       >::type* = 0)
1426     : detail::any_executor_base(BOOST_ASIO_MOVE_CAST(
1427           any_executor<OtherSupportableProperties...>)(other), true_type()),
1428       prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())
1429   {
1430   }
1431 
1432   any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1433     : detail::any_executor_base(
1434         static_cast<const detail::any_executor_base&>(other)),
1435       prop_fns_(other.prop_fns_)
1436   {
1437   }
1438 
1439   any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1440   {
1441     if (this != &other)
1442     {
1443       prop_fns_ = other.prop_fns_;
1444       detail::any_executor_base::operator=(
1445           static_cast<const detail::any_executor_base&>(other));
1446     }
1447     return *this;
1448   }
1449 
1450   any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1451   {
1452     prop_fns_ = prop_fns_table<void>();
1453     detail::any_executor_base::operator=(p);
1454     return *this;
1455   }
1456 
1457 #if defined(BOOST_ASIO_HAS_MOVE)
1458 
1459   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1460     : detail::any_executor_base(
1461         static_cast<any_executor_base&&>(
1462           static_cast<any_executor_base&>(other))),
1463       prop_fns_(other.prop_fns_)
1464   {
1465     other.prop_fns_ = prop_fns_table<void>();
1466   }
1467 
1468   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1469   {
1470     if (this != &other)
1471     {
1472       prop_fns_ = other.prop_fns_;
1473       detail::any_executor_base::operator=(
1474           static_cast<detail::any_executor_base&&>(
1475             static_cast<detail::any_executor_base&>(other)));
1476     }
1477     return *this;
1478   }
1479 
1480 #endif // defined(BOOST_ASIO_HAS_MOVE)
1481 
1482   void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1483   {
1484     if (this != &other)
1485     {
1486       detail::any_executor_base::swap(
1487           static_cast<detail::any_executor_base&>(other));
1488       const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_;
1489       other.prop_fns_ = prop_fns_;
1490       prop_fns_ = tmp_prop_fns;
1491     }
1492   }
1493 
1494   using detail::any_executor_base::execute;
1495   using detail::any_executor_base::target;
1496   using detail::any_executor_base::target_type;
1497   using detail::any_executor_base::operator unspecified_bool_type;
1498   using detail::any_executor_base::operator!;
1499 
1500   bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1501   {
1502     return any_executor_base::equality_helper(other);
1503   }
1504 
1505   template <typename AnyExecutor1, typename AnyExecutor2>
1506   friend typename enable_if<
1507     is_same<AnyExecutor1, any_executor>::value
1508       || is_same<AnyExecutor2, any_executor>::value,
1509     bool
1510   >::type operator==(const AnyExecutor1& a,
1511       const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1512   {
1513     return static_cast<const any_executor&>(a).equality_helper(b);
1514   }
1515 
1516   template <typename AnyExecutor>
1517   friend typename enable_if<
1518     is_same<AnyExecutor, any_executor>::value,
1519     bool
1520   >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1521   {
1522     return !a;
1523   }
1524 
1525   template <typename AnyExecutor>
1526   friend typename enable_if<
1527     is_same<AnyExecutor, any_executor>::value,
1528     bool
1529   >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1530   {
1531     return !b;
1532   }
1533 
1534   template <typename AnyExecutor1, typename AnyExecutor2>
1535   friend typename enable_if<
1536     is_same<AnyExecutor1, any_executor>::value
1537       || is_same<AnyExecutor2, any_executor>::value,
1538     bool
1539   >::type operator!=(const AnyExecutor1& a,
1540       const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT
1541   {
1542     return !static_cast<const any_executor&>(a).equality_helper(b);
1543   }
1544 
1545   template <typename AnyExecutor>
1546   friend typename enable_if<
1547     is_same<AnyExecutor, any_executor>::value,
1548     bool
1549   >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1550   {
1551     return !!a;
1552   }
1553 
1554   template <typename AnyExecutor>
1555   friend typename enable_if<
1556     is_same<AnyExecutor, any_executor>::value,
1557     bool
1558   >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT
1559   {
1560     return !!b;
1561   }
1562 
1563   template <typename T>
1564   struct find_convertible_property :
1565       detail::supportable_properties<
1566         0, void(SupportableProperties...)>::template
1567           find_convertible_property<T> {};
1568 
1569   template <typename Property>
1570   void query(const Property& p,
1571       typename enable_if<
1572         is_same<
1573           typename find_convertible_property<Property>::query_result_type,
1574           void
1575         >::value
1576       >::type* = 0) const
1577   {
1578     typedef find_convertible_property<Property> found;
1579     prop_fns_[found::index].query(0, object_fns_->target(*this),
1580         &static_cast<const typename found::type&>(p));
1581   }
1582 
1583   template <typename Property>
1584   typename find_convertible_property<Property>::query_result_type
1585   query(const Property& p,
1586       typename enable_if<
1587         !is_same<
1588           typename find_convertible_property<Property>::query_result_type,
1589           void
1590         >::value
1591         &&
1592         is_reference<
1593           typename find_convertible_property<Property>::query_result_type
1594         >::value
1595       >::type* = 0) const
1596   {
1597     typedef find_convertible_property<Property> found;
1598     typename remove_reference<
1599       typename found::query_result_type>::type* result = 0;
1600     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1601         &static_cast<const typename found::type&>(p));
1602     return *result;
1603   }
1604 
1605   template <typename Property>
1606   typename find_convertible_property<Property>::query_result_type
1607   query(const Property& p,
1608       typename enable_if<
1609         !is_same<
1610           typename find_convertible_property<Property>::query_result_type,
1611           void
1612         >::value
1613         &&
1614         is_scalar<
1615           typename find_convertible_property<Property>::query_result_type
1616         >::value
1617       >::type* = 0) const
1618   {
1619     typedef find_convertible_property<Property> found;
1620     typename found::query_result_type result;
1621     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1622         &static_cast<const typename found::type&>(p));
1623     return result;
1624   }
1625 
1626   template <typename Property>
1627   typename find_convertible_property<Property>::query_result_type
1628   query(const Property& p,
1629       typename enable_if<
1630         !is_same<
1631           typename find_convertible_property<Property>::query_result_type,
1632           void
1633         >::value
1634         &&
1635         !is_reference<
1636           typename find_convertible_property<Property>::query_result_type
1637         >::value
1638         &&
1639         !is_scalar<
1640           typename find_convertible_property<Property>::query_result_type
1641         >::value
1642       >::type* = 0) const
1643   {
1644     typedef find_convertible_property<Property> found;
1645     typename found::query_result_type* result;
1646     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1647         &static_cast<const typename found::type&>(p));
1648     return *boost::asio::detail::scoped_ptr<
1649       typename found::query_result_type>(result);
1650   }
1651 
1652   template <typename T>
1653   struct find_convertible_requirable_property :
1654       detail::supportable_properties<
1655         0, void(SupportableProperties...)>::template
1656           find_convertible_requirable_property<T> {};
1657 
1658   template <typename Property>
1659   any_executor require(const Property& p,
1660       typename enable_if<
1661         find_convertible_requirable_property<Property>::value
1662       >::type* = 0) const
1663   {
1664     typedef find_convertible_requirable_property<Property> found;
1665     return prop_fns_[found::index].require(object_fns_->target(*this),
1666         &static_cast<const typename found::type&>(p));
1667   }
1668 
1669   template <typename T>
1670   struct find_convertible_preferable_property :
1671       detail::supportable_properties<
1672         0, void(SupportableProperties...)>::template
1673           find_convertible_preferable_property<T> {};
1674 
1675   template <typename Property>
1676   any_executor prefer(const Property& p,
1677       typename enable_if<
1678         find_convertible_preferable_property<Property>::value
1679       >::type* = 0) const
1680   {
1681     typedef find_convertible_preferable_property<Property> found;
1682     return prop_fns_[found::index].prefer(object_fns_->target(*this),
1683         &static_cast<const typename found::type&>(p));
1684   }
1685 
1686 //private:
1687   template <typename Ex>
1688   static const prop_fns<any_executor>* prop_fns_table()
1689   {
1690     static const prop_fns<any_executor> fns[] =
1691     {
1692       {
1693         &detail::any_executor_base::query_fn<
1694             Ex, SupportableProperties>,
1695         &detail::any_executor_base::require_fn<
1696             any_executor, Ex, SupportableProperties>,
1697         &detail::any_executor_base::prefer_fn<
1698             any_executor, Ex, SupportableProperties>
1699       }...
1700     };
1701     return fns;
1702   }
1703 
1704   const prop_fns<any_executor>* prop_fns_;
1705 };
1706 
1707 template <typename... SupportableProperties>
1708 inline void swap(any_executor<SupportableProperties...>& a,
1709     any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1710 {
1711   return a.swap(b);
1712 }
1713 
1714 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1715 
1716 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
1717   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n
1718 
1719 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \
1720   {  \
1721     &detail::any_executor_base::query_fn<Ex, T1>, \
1722     &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \
1723     &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \
1724   }
1725 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \
1726   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \
1727   { \
1728     &detail::any_executor_base::query_fn<Ex, T2>, \
1729     &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \
1730     &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \
1731   }
1732 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \
1733   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \
1734   { \
1735     &detail::any_executor_base::query_fn<Ex, T3>, \
1736     &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \
1737     &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \
1738   }
1739 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \
1740   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \
1741   { \
1742     &detail::any_executor_base::query_fn<Ex, T4>, \
1743     &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \
1744     &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \
1745   }
1746 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \
1747   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \
1748   { \
1749     &detail::any_executor_base::query_fn<Ex, T5>, \
1750     &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \
1751     &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \
1752   }
1753 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \
1754   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \
1755   { \
1756     &detail::any_executor_base::query_fn<Ex, T6>, \
1757     &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \
1758     &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \
1759   }
1760 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \
1761   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \
1762   { \
1763     &detail::any_executor_base::query_fn<Ex, T7>, \
1764     &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \
1765     &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \
1766   }
1767 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \
1768   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \
1769   { \
1770     &detail::any_executor_base::query_fn<Ex, T8>, \
1771     &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \
1772     &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \
1773   }
1774 
1775 #if defined(BOOST_ASIO_HAS_MOVE)
1776 
1777 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1778   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1779     : detail::any_executor_base( \
1780         static_cast<any_executor_base&&>( \
1781           static_cast<any_executor_base&>(other))), \
1782       prop_fns_(other.prop_fns_) \
1783   { \
1784     other.prop_fns_ = prop_fns_table<void>(); \
1785   } \
1786   \
1787   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1788   { \
1789     if (this != &other) \
1790     { \
1791       prop_fns_ = other.prop_fns_; \
1792       detail::any_executor_base::operator=( \
1793           static_cast<detail::any_executor_base&&>( \
1794             static_cast<detail::any_executor_base&>(other))); \
1795     } \
1796     return *this; \
1797   } \
1798   /**/
1799 #else // defined(BOOST_ASIO_HAS_MOVE)
1800 
1801 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
1802 
1803 #endif // defined(BOOST_ASIO_HAS_MOVE)
1804 
1805 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \
1806   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
1807   class any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> : \
1808     public detail::any_executor_base, \
1809     public detail::any_executor_context< \
1810       any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, \
1811         typename detail::supportable_properties< \
1812           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \
1813   { \
1814   public: \
1815     any_executor() BOOST_ASIO_NOEXCEPT \
1816       : detail::any_executor_base(), \
1817         prop_fns_(prop_fns_table<void>()) \
1818     { \
1819     } \
1820     \
1821     any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT \
1822       : detail::any_executor_base(), \
1823         prop_fns_(prop_fns_table<void>()) \
1824     { \
1825     } \
1826     \
1827     template <BOOST_ASIO_EXECUTION_EXECUTOR Executor> \
1828     any_executor(Executor ex, \
1829         typename enable_if< \
1830           conditional< \
1831             !is_same<Executor, any_executor>::value \
1832               && !is_base_of<detail::any_executor_base, Executor>::value, \
1833             detail::is_valid_target_executor< \
1834               Executor, void(BOOST_ASIO_VARIADIC_TARGS(n))>, \
1835             false_type \
1836           >::type::value \
1837         >::type* = 0) \
1838       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1839             Executor)(ex), false_type()), \
1840         prop_fns_(prop_fns_table<Executor>()) \
1841     { \
1842     } \
1843     \
1844     any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1845       : detail::any_executor_base( \
1846           static_cast<const detail::any_executor_base&>(other)), \
1847         prop_fns_(other.prop_fns_) \
1848     { \
1849     } \
1850     \
1851     any_executor(any_executor<> other) \
1852       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1853             any_executor<>)(other), true_type()), \
1854         prop_fns_(prop_fns_table<any_executor<> >()) \
1855     { \
1856     } \
1857     \
1858     template <typename OtherAnyExecutor> \
1859     any_executor(OtherAnyExecutor other, \
1860         typename enable_if< \
1861           conditional< \
1862             !is_same<OtherAnyExecutor, any_executor>::value \
1863               && is_base_of<detail::any_executor_base, \
1864                 OtherAnyExecutor>::value, \
1865             typename detail::supportable_properties< \
1866               0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1867                 is_valid_target<OtherAnyExecutor>, \
1868             false_type \
1869           >::type::value \
1870         >::type* = 0) \
1871       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1872             OtherAnyExecutor)(other), true_type()), \
1873         prop_fns_(prop_fns_table<OtherAnyExecutor>()) \
1874     { \
1875     } \
1876     \
1877     any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1878     { \
1879       if (this != &other) \
1880       { \
1881         prop_fns_ = other.prop_fns_; \
1882         detail::any_executor_base::operator=( \
1883             static_cast<const detail::any_executor_base&>(other)); \
1884       } \
1885       return *this; \
1886     } \
1887     \
1888     any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT \
1889     { \
1890       prop_fns_ = prop_fns_table<void>(); \
1891       detail::any_executor_base::operator=(p); \
1892       return *this; \
1893     } \
1894     \
1895     BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1896     \
1897     void swap(any_executor& other) BOOST_ASIO_NOEXCEPT \
1898     { \
1899       if (this != &other) \
1900       { \
1901         detail::any_executor_base::swap( \
1902             static_cast<detail::any_executor_base&>(other)); \
1903         const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \
1904         other.prop_fns_ = prop_fns_; \
1905         prop_fns_ = tmp_prop_fns; \
1906       } \
1907     } \
1908     \
1909     using detail::any_executor_base::execute; \
1910     using detail::any_executor_base::target; \
1911     using detail::any_executor_base::target_type; \
1912     using detail::any_executor_base::operator unspecified_bool_type; \
1913     using detail::any_executor_base::operator!; \
1914     \
1915     bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT \
1916     { \
1917       return any_executor_base::equality_helper(other); \
1918     } \
1919     \
1920     template <typename AnyExecutor1, typename AnyExecutor2> \
1921     friend typename enable_if< \
1922       is_same<AnyExecutor1, any_executor>::value \
1923         || is_same<AnyExecutor2, any_executor>::value, \
1924       bool \
1925     >::type operator==(const AnyExecutor1& a, \
1926         const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT \
1927     { \
1928       return static_cast<const any_executor&>(a).equality_helper(b); \
1929     } \
1930     \
1931     template <typename AnyExecutor> \
1932     friend typename enable_if< \
1933       is_same<AnyExecutor, any_executor>::value, \
1934       bool \
1935     >::type operator==(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT \
1936     { \
1937       return !a; \
1938     } \
1939     \
1940     template <typename AnyExecutor> \
1941     friend typename enable_if< \
1942       is_same<AnyExecutor, any_executor>::value, \
1943       bool \
1944     >::type operator==(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT \
1945     { \
1946       return !b; \
1947     } \
1948     \
1949     template <typename AnyExecutor1, typename AnyExecutor2> \
1950     friend typename enable_if< \
1951       is_same<AnyExecutor1, any_executor>::value \
1952         || is_same<AnyExecutor2, any_executor>::value, \
1953       bool \
1954     >::type operator!=(const AnyExecutor1& a, \
1955         const AnyExecutor2& b) BOOST_ASIO_NOEXCEPT \
1956     { \
1957       return !static_cast<const any_executor&>(a).equality_helper(b); \
1958     } \
1959     \
1960     template <typename AnyExecutor> \
1961     friend typename enable_if< \
1962       is_same<AnyExecutor, any_executor>::value, \
1963       bool \
1964     >::type operator!=(const AnyExecutor& a, nullptr_t) BOOST_ASIO_NOEXCEPT \
1965     { \
1966       return !!a; \
1967     } \
1968     \
1969     template <typename AnyExecutor> \
1970     friend typename enable_if< \
1971       is_same<AnyExecutor, any_executor>::value, \
1972       bool \
1973     >::type operator!=(nullptr_t, const AnyExecutor& b) BOOST_ASIO_NOEXCEPT \
1974     { \
1975       return !!b; \
1976     } \
1977     \
1978     template <typename T> \
1979     struct find_convertible_property : \
1980         detail::supportable_properties< \
1981           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1982             find_convertible_property<T> {}; \
1983     \
1984     template <typename Property> \
1985     void query(const Property& p, \
1986         typename enable_if< \
1987           is_same< \
1988             typename find_convertible_property<Property>::query_result_type, \
1989             void \
1990           >::value \
1991         >::type* = 0) const \
1992     { \
1993       typedef find_convertible_property<Property> found; \
1994       prop_fns_[found::index].query(0, object_fns_->target(*this), \
1995           &static_cast<const typename found::type&>(p)); \
1996     } \
1997     \
1998     template <typename Property> \
1999     typename find_convertible_property<Property>::query_result_type \
2000     query(const Property& p, \
2001         typename enable_if< \
2002           !is_same< \
2003             typename find_convertible_property<Property>::query_result_type, \
2004             void \
2005           >::value \
2006           && \
2007           is_reference< \
2008             typename find_convertible_property<Property>::query_result_type \
2009           >::value \
2010         >::type* = 0) const \
2011     { \
2012       typedef find_convertible_property<Property> found; \
2013       typename remove_reference< \
2014         typename found::query_result_type>::type* result; \
2015       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2016           &static_cast<const typename found::type&>(p)); \
2017       return *result; \
2018     } \
2019     \
2020     template <typename Property> \
2021     typename find_convertible_property<Property>::query_result_type \
2022     query(const Property& p, \
2023         typename enable_if< \
2024           !is_same< \
2025             typename find_convertible_property<Property>::query_result_type, \
2026             void \
2027           >::value \
2028           && \
2029           is_scalar< \
2030             typename find_convertible_property<Property>::query_result_type \
2031           >::value \
2032         >::type* = 0) const \
2033     { \
2034       typedef find_convertible_property<Property> found; \
2035       typename found::query_result_type result; \
2036       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2037           &static_cast<const typename found::type&>(p)); \
2038       return result; \
2039     } \
2040     \
2041     template <typename Property> \
2042     typename find_convertible_property<Property>::query_result_type \
2043     query(const Property& p, \
2044         typename enable_if< \
2045           !is_same< \
2046             typename find_convertible_property<Property>::query_result_type, \
2047             void \
2048           >::value \
2049           && \
2050           !is_reference< \
2051             typename find_convertible_property<Property>::query_result_type \
2052           >::value \
2053           && \
2054           !is_scalar< \
2055             typename find_convertible_property<Property>::query_result_type \
2056           >::value \
2057         >::type* = 0) const \
2058     { \
2059       typedef find_convertible_property<Property> found; \
2060       typename found::query_result_type* result; \
2061       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
2062           &static_cast<const typename found::type&>(p)); \
2063       return *boost::asio::detail::scoped_ptr< \
2064         typename found::query_result_type>(result); \
2065     } \
2066     \
2067     template <typename T> \
2068     struct find_convertible_requirable_property : \
2069         detail::supportable_properties< \
2070           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2071             find_convertible_requirable_property<T> {}; \
2072     \
2073     template <typename Property> \
2074     any_executor require(const Property& p, \
2075         typename enable_if< \
2076           find_convertible_requirable_property<Property>::value \
2077         >::type* = 0) const \
2078     { \
2079       typedef find_convertible_requirable_property<Property> found; \
2080       return prop_fns_[found::index].require(object_fns_->target(*this), \
2081           &static_cast<const typename found::type&>(p)); \
2082     } \
2083     \
2084     template <typename T> \
2085     struct find_convertible_preferable_property : \
2086         detail::supportable_properties< \
2087           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2088             find_convertible_preferable_property<T> {}; \
2089     \
2090     template <typename Property> \
2091     any_executor prefer(const Property& p, \
2092         typename enable_if< \
2093           find_convertible_preferable_property<Property>::value \
2094         >::type* = 0) const \
2095     { \
2096       typedef find_convertible_preferable_property<Property> found; \
2097       return prop_fns_[found::index].prefer(object_fns_->target(*this), \
2098           &static_cast<const typename found::type&>(p)); \
2099     } \
2100     \
2101     template <typename Ex> \
2102     static const prop_fns<any_executor>* prop_fns_table() \
2103     { \
2104       static const prop_fns<any_executor> fns[] = \
2105       { \
2106         BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
2107       }; \
2108       return fns; \
2109     } \
2110     \
2111     const prop_fns<any_executor>* prop_fns_; \
2112     typedef detail::supportable_properties<0, \
2113         void(BOOST_ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \
2114   }; \
2115   \
2116   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2117   inline void swap(any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2118       any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2119   { \
2120     return a.swap(b); \
2121   } \
2122   /**/
2123   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF)
2124 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF
2125 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
2126 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS
2127 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1
2128 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2
2129 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3
2130 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4
2131 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5
2132 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6
2133 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7
2134 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8
2135 
2136 #endif // if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2137 
2138 } // namespace execution
2139 namespace traits {
2140 
2141 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2142 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2143 
2144 template <typename... SupportableProperties>
2145 struct equality_comparable<execution::any_executor<SupportableProperties...> >
2146 {
2147   static const bool is_valid = true;
2148   static const bool is_noexcept = true;
2149 };
2150 
2151 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2152 
2153 template <>
2154 struct equality_comparable<execution::any_executor<> >
2155 {
2156   static const bool is_valid = true;
2157   static const bool is_noexcept = true;
2158 };
2159 
2160 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \
2161   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2162   struct equality_comparable< \
2163       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> > \
2164   { \
2165     static const bool is_valid = true; \
2166     static const bool is_noexcept = true; \
2167   }; \
2168   /**/
2169   BOOST_ASIO_VARIADIC_GENERATE(
2170       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF)
2171 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF
2172 
2173 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2174 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2175 
2176 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2177 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2178 
2179 template <typename F, typename... SupportableProperties>
2180 struct execute_member<execution::any_executor<SupportableProperties...>, F>
2181 {
2182   static const bool is_valid = true;
2183   static const bool is_noexcept = false;
2184   typedef void result_type;
2185 };
2186 
2187 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2188 
2189 template <typename F>
2190 struct execute_member<execution::any_executor<>, F>
2191 {
2192   static const bool is_valid = true;
2193   static const bool is_noexcept = false;
2194   typedef void result_type;
2195 };
2196 
2197 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \
2198   template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2199   struct execute_member< \
2200       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, F> \
2201   { \
2202     static const bool is_valid = true; \
2203     static const bool is_noexcept = false; \
2204     typedef void result_type; \
2205   }; \
2206   /**/
2207   BOOST_ASIO_VARIADIC_GENERATE(
2208       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF)
2209 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF
2210 
2211 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2212 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2213 
2214 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2215 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2216 
2217 template <typename Prop, typename... SupportableProperties>
2218 struct query_member<
2219     execution::any_executor<SupportableProperties...>, Prop,
2220     typename enable_if<
2221       execution::detail::supportable_properties<
2222         0, void(SupportableProperties...)>::template
2223           find_convertible_property<Prop>::value
2224     >::type>
2225 {
2226   static const bool is_valid = true;
2227   static const bool is_noexcept = false;
2228   typedef typename execution::detail::supportable_properties<
2229       0, void(SupportableProperties...)>::template
2230         find_convertible_property<Prop>::query_result_type result_type;
2231 };
2232 
2233 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2234 
2235 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \
2236   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2237   struct query_member< \
2238       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2239       typename enable_if< \
2240         execution::detail::supportable_properties< \
2241           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2242             find_convertible_property<Prop>::value \
2243     >::type> \
2244   { \
2245     static const bool is_valid = true; \
2246     static const bool is_noexcept = false; \
2247     typedef typename execution::detail::supportable_properties< \
2248         0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2249           find_convertible_property<Prop>::query_result_type result_type; \
2250   }; \
2251   /**/
2252   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF)
2253 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF
2254 
2255 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2256 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2257 
2258 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2259 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2260 
2261 template <typename Prop, typename... SupportableProperties>
2262 struct require_member<
2263     execution::any_executor<SupportableProperties...>, Prop,
2264     typename enable_if<
2265       execution::detail::supportable_properties<
2266         0, void(SupportableProperties...)>::template
2267           find_convertible_requirable_property<Prop>::value
2268     >::type>
2269 {
2270   static const bool is_valid = true;
2271   static const bool is_noexcept = false;
2272   typedef execution::any_executor<SupportableProperties...> result_type;
2273 };
2274 
2275 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2276 
2277 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \
2278   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2279   struct require_member< \
2280       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2281       typename enable_if< \
2282         execution::detail::supportable_properties< \
2283           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2284             find_convertible_requirable_property<Prop>::value \
2285       >::type> \
2286   { \
2287     static const bool is_valid = true; \
2288     static const bool is_noexcept = false; \
2289     typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2290   }; \
2291   /**/
2292   BOOST_ASIO_VARIADIC_GENERATE(
2293       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF)
2294 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF
2295 
2296 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2297 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2298 
2299 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2300 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2301 
2302 template <typename Prop, typename... SupportableProperties>
2303 struct prefer_member<
2304     execution::any_executor<SupportableProperties...>, Prop,
2305     typename enable_if<
2306       execution::detail::supportable_properties<
2307         0, void(SupportableProperties...)>::template
2308           find_convertible_preferable_property<Prop>::value
2309     >::type>
2310 {
2311   static const bool is_valid = true;
2312   static const bool is_noexcept = false;
2313   typedef execution::any_executor<SupportableProperties...> result_type;
2314 };
2315 
2316 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2317 
2318 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \
2319   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2320   struct prefer_member< \
2321       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2322       typename enable_if< \
2323         execution::detail::supportable_properties< \
2324           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2325             find_convertible_preferable_property<Prop>::value \
2326       >::type> \
2327   { \
2328     static const bool is_valid = true; \
2329     static const bool is_noexcept = false; \
2330     typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2331   }; \
2332   /**/
2333   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF)
2334 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF
2335 
2336 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2337 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2338 
2339 } // namespace traits
2340 
2341 #endif // defined(GENERATING_DOCUMENTATION)
2342 
2343 } // namespace asio
2344 } // namespace boost
2345 
2346 #include <boost/asio/detail/pop_options.hpp>
2347 
2348 #endif // BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP
2349