• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // execution/any_executor.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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   const std::type_info& target_type() const
624   {
625     return target_fns_->target_type();
626   }
627 
628   struct unspecified_bool_type_t {};
629   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
630   static void unspecified_bool_true(unspecified_bool_type_t) {}
631 
632   operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
633   {
634     return target_ ? &any_executor_base::unspecified_bool_true : 0;
635   }
636 
637   bool operator!() const BOOST_ASIO_NOEXCEPT
638   {
639     return target_ == 0;
640   }
641 
642 protected:
643   bool equality_helper(const any_executor_base& other) const BOOST_ASIO_NOEXCEPT
644   {
645     if (target_ == other.target_)
646       return true;
647     if (target_ && !other.target_)
648       return false;
649     if (!target_ && other.target_)
650       return false;
651     if (target_fns_ != other.target_fns_)
652       return false;
653     return target_fns_->equal(*this, other);
654   }
655 
656   template <typename Ex>
657   Ex& object()
658   {
659     return *static_cast<Ex*>(static_cast<void*>(&object_));
660   }
661 
662   template <typename Ex>
663   const Ex& object() const
664   {
665     return *static_cast<const Ex*>(static_cast<const void*>(&object_));
666   }
667 
668   struct object_fns
669   {
670     void (*destroy)(any_executor_base&);
671     void (*copy)(any_executor_base&, const any_executor_base&);
672     void (*move)(any_executor_base&, any_executor_base&);
673     const void* (*target)(const any_executor_base&);
674   };
675 
676   static void destroy_void(any_executor_base&)
677   {
678   }
679 
680   static void copy_void(any_executor_base& ex1, const any_executor_base&)
681   {
682     ex1.target_ = 0;
683   }
684 
685   static void move_void(any_executor_base& ex1, any_executor_base&)
686   {
687     ex1.target_ = 0;
688   }
689 
690   static const void* target_void(const any_executor_base&)
691   {
692     return 0;
693   }
694 
695   template <typename Obj>
696   static const object_fns* object_fns_table(
697       typename enable_if<
698         is_same<Obj, void>::value
699       >::type* = 0)
700   {
701     static const object_fns fns =
702     {
703       &any_executor_base::destroy_void,
704       &any_executor_base::copy_void,
705       &any_executor_base::move_void,
706       &any_executor_base::target_void
707     };
708     return &fns;
709   }
710 
711   static void destroy_shared(any_executor_base& ex)
712   {
713     typedef boost::asio::detail::shared_ptr<void> type;
714     ex.object<type>().~type();
715   }
716 
717   static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)
718   {
719     typedef boost::asio::detail::shared_ptr<void> type;
720     new (&ex1.object_) type(ex2.object<type>());
721     ex1.target_ = ex2.target_;
722   }
723 
724   static void move_shared(any_executor_base& ex1, any_executor_base& ex2)
725   {
726     typedef boost::asio::detail::shared_ptr<void> type;
727     new (&ex1.object_) type(BOOST_ASIO_MOVE_CAST(type)(ex2.object<type>()));
728     ex1.target_ = ex2.target_;
729     ex2.object<type>().~type();
730   }
731 
732   static const void* target_shared(const any_executor_base& ex)
733   {
734     typedef boost::asio::detail::shared_ptr<void> type;
735     return ex.object<type>().get();
736   }
737 
738   template <typename Obj>
739   static const object_fns* object_fns_table(
740       typename enable_if<
741         is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
742       >::type* = 0)
743   {
744     static const object_fns fns =
745     {
746       &any_executor_base::destroy_shared,
747       &any_executor_base::copy_shared,
748       &any_executor_base::move_shared,
749       &any_executor_base::target_shared
750     };
751     return &fns;
752   }
753 
754   template <typename Obj>
755   static void destroy_object(any_executor_base& ex)
756   {
757     ex.object<Obj>().~Obj();
758   }
759 
760   template <typename Obj>
761   static void copy_object(any_executor_base& ex1, const any_executor_base& ex2)
762   {
763     new (&ex1.object_) Obj(ex2.object<Obj>());
764     ex1.target_ = &ex1.object<Obj>();
765   }
766 
767   template <typename Obj>
768   static void move_object(any_executor_base& ex1, any_executor_base& ex2)
769   {
770     new (&ex1.object_) Obj(BOOST_ASIO_MOVE_CAST(Obj)(ex2.object<Obj>()));
771     ex1.target_ = &ex1.object<Obj>();
772     ex2.object<Obj>().~Obj();
773   }
774 
775   template <typename Obj>
776   static const void* target_object(const any_executor_base& ex)
777   {
778     return &ex.object<Obj>();
779   }
780 
781   template <typename Obj>
782   static const object_fns* object_fns_table(
783       typename enable_if<
784         !is_same<Obj, void>::value
785           && !is_same<Obj, boost::asio::detail::shared_ptr<void> >::value
786       >::type* = 0)
787   {
788     static const object_fns fns =
789     {
790       &any_executor_base::destroy_object<Obj>,
791       &any_executor_base::copy_object<Obj>,
792       &any_executor_base::move_object<Obj>,
793       &any_executor_base::target_object<Obj>
794     };
795     return &fns;
796   }
797 
798   typedef boost::asio::detail::executor_function function;
799   typedef boost::asio::detail::executor_function_view function_view;
800 
801   struct target_fns
802   {
803     const std::type_info& (*target_type)();
804     bool (*equal)(const any_executor_base&, const any_executor_base&);
805     void (*execute)(const any_executor_base&, BOOST_ASIO_MOVE_ARG(function));
806     void (*blocking_execute)(const any_executor_base&, function_view);
807   };
808 
809   static const std::type_info& target_type_void()
810   {
811     return typeid(void);
812   }
813 
814   static bool equal_void(const any_executor_base&, const any_executor_base&)
815   {
816     return true;
817   }
818 
819   static void execute_void(const any_executor_base&,
820       BOOST_ASIO_MOVE_ARG(function))
821   {
822     bad_executor ex;
823     boost::asio::detail::throw_exception(ex);
824   }
825 
826   static void blocking_execute_void(const any_executor_base&, function_view)
827   {
828     bad_executor ex;
829     boost::asio::detail::throw_exception(ex);
830   }
831 
832   template <typename Ex>
833   static const target_fns* target_fns_table(
834       typename enable_if<
835         is_same<Ex, void>::value
836       >::type* = 0)
837   {
838     static const target_fns fns =
839     {
840       &any_executor_base::target_type_void,
841       &any_executor_base::equal_void,
842       &any_executor_base::execute_void,
843       &any_executor_base::blocking_execute_void
844     };
845     return &fns;
846   }
847 
848   template <typename Ex>
849   static const std::type_info& target_type_ex()
850   {
851     return typeid(Ex);
852   }
853 
854   template <typename Ex>
855   static bool equal_ex(const any_executor_base& ex1,
856       const any_executor_base& ex2)
857   {
858     return *ex1.target<Ex>() == *ex2.target<Ex>();
859   }
860 
861   template <typename Ex>
862   static void execute_ex(const any_executor_base& ex,
863       BOOST_ASIO_MOVE_ARG(function) f)
864   {
865     execution::execute(*ex.target<Ex>(), BOOST_ASIO_MOVE_CAST(function)(f));
866   }
867 
868   template <typename Ex>
869   static void blocking_execute_ex(const any_executor_base& ex, function_view f)
870   {
871     execution::execute(*ex.target<Ex>(), f);
872   }
873 
874   template <typename Ex>
875   static const target_fns* target_fns_table(bool is_always_blocking,
876       typename enable_if<
877         !is_same<Ex, void>::value
878       >::type* = 0)
879   {
880     static const target_fns fns_with_execute =
881     {
882       &any_executor_base::target_type_ex<Ex>,
883       &any_executor_base::equal_ex<Ex>,
884       &any_executor_base::execute_ex<Ex>,
885       0
886     };
887 
888     static const target_fns fns_with_blocking_execute =
889     {
890       &any_executor_base::target_type_ex<Ex>,
891       &any_executor_base::equal_ex<Ex>,
892       0,
893       &any_executor_base::blocking_execute_ex<Ex>
894     };
895 
896     return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute;
897   }
898 
899 #if defined(BOOST_ASIO_MSVC)
900 # pragma warning (push)
901 # pragma warning (disable:4702)
902 #endif // defined(BOOST_ASIO_MSVC)
903 
904   static void query_fn_void(void*, const void*, const void*)
905   {
906     bad_executor ex;
907     boost::asio::detail::throw_exception(ex);
908   }
909 
910   template <typename Ex, class Prop>
911   static void query_fn_non_void(void*, const void* ex, const void* prop,
912       typename enable_if<
913         boost::asio::can_query<const Ex&, const Prop&>::value
914           && is_same<typename Prop::polymorphic_query_result_type, void>::value
915       >::type*)
916   {
917     boost::asio::query(*static_cast<const Ex*>(ex),
918         *static_cast<const Prop*>(prop));
919   }
920 
921   template <typename Ex, class Prop>
922   static void query_fn_non_void(void*, const void*, const void*,
923       typename enable_if<
924         !boost::asio::can_query<const Ex&, const Prop&>::value
925           && is_same<typename Prop::polymorphic_query_result_type, void>::value
926       >::type*)
927   {
928   }
929 
930   template <typename Ex, class Prop>
931   static void query_fn_non_void(void* result, const void* ex, const void* prop,
932       typename enable_if<
933         boost::asio::can_query<const Ex&, const Prop&>::value
934           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
935           && is_reference<typename Prop::polymorphic_query_result_type>::value
936       >::type*)
937   {
938     *static_cast<typename remove_reference<
939       typename Prop::polymorphic_query_result_type>::type**>(result)
940         = &static_cast<typename Prop::polymorphic_query_result_type>(
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           && is_reference<typename Prop::polymorphic_query_result_type>::value
951       >::type*)
952   {
953     std::terminate(); // Combination should not be possible.
954   }
955 
956   template <typename Ex, class Prop>
957   static void query_fn_non_void(void* result, const void* ex, const void* prop,
958       typename enable_if<
959         boost::asio::can_query<const Ex&, const Prop&>::value
960           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
961           && is_scalar<typename Prop::polymorphic_query_result_type>::value
962       >::type*)
963   {
964     *static_cast<typename Prop::polymorphic_query_result_type*>(result)
965       = static_cast<typename Prop::polymorphic_query_result_type>(
966           boost::asio::query(*static_cast<const Ex*>(ex),
967             *static_cast<const Prop*>(prop)));
968   }
969 
970   template <typename Ex, class Prop>
971   static void query_fn_non_void(void* result, const void*, const void*,
972       typename enable_if<
973         !boost::asio::can_query<const Ex&, const Prop&>::value
974           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
975           && is_scalar<typename Prop::polymorphic_query_result_type>::value
976       >::type*)
977   {
978     *static_cast<typename Prop::polymorphic_query_result_type*>(result)
979       = typename Prop::polymorphic_query_result_type();
980   }
981 
982   template <typename Ex, class Prop>
983   static void query_fn_non_void(void* result, const void* ex, const void* prop,
984       typename enable_if<
985         boost::asio::can_query<const Ex&, const Prop&>::value
986           && !is_same<typename Prop::polymorphic_query_result_type, void>::value
987           && !is_reference<typename Prop::polymorphic_query_result_type>::value
988           && !is_scalar<typename Prop::polymorphic_query_result_type>::value
989       >::type*)
990   {
991     *static_cast<typename Prop::polymorphic_query_result_type**>(result)
992       = new typename Prop::polymorphic_query_result_type(
993           boost::asio::query(*static_cast<const Ex*>(ex),
994             *static_cast<const Prop*>(prop)));
995   }
996 
997   template <typename Ex, class Prop>
998   static void query_fn_non_void(void* result, const void*, const void*, ...)
999   {
1000     *static_cast<typename Prop::polymorphic_query_result_type**>(result)
1001       = new typename Prop::polymorphic_query_result_type();
1002   }
1003 
1004   template <typename Ex, class Prop>
1005   static void query_fn_impl(void* result, const void* ex, const void* prop,
1006       typename enable_if<
1007         is_same<Ex, void>::value
1008       >::type*)
1009   {
1010     query_fn_void(result, ex, prop);
1011   }
1012 
1013   template <typename Ex, class Prop>
1014   static void query_fn_impl(void* result, const void* ex, const void* prop,
1015       typename enable_if<
1016         !is_same<Ex, void>::value
1017       >::type*)
1018   {
1019     query_fn_non_void<Ex, Prop>(result, ex, prop, 0);
1020   }
1021 
1022   template <typename Ex, class Prop>
1023   static void query_fn(void* result, const void* ex, const void* prop)
1024   {
1025     query_fn_impl<Ex, Prop>(result, ex, prop, 0);
1026   }
1027 
1028   template <typename Poly, typename Ex, class Prop>
1029   static Poly require_fn_impl(const void*, const void*,
1030       typename enable_if<
1031         is_same<Ex, void>::value
1032       >::type*)
1033   {
1034     bad_executor ex;
1035     boost::asio::detail::throw_exception(ex);
1036     return Poly();
1037   }
1038 
1039   template <typename Poly, typename Ex, class Prop>
1040   static Poly require_fn_impl(const void* ex, const void* prop,
1041       typename enable_if<
1042         !is_same<Ex, void>::value && Prop::is_requirable
1043       >::type*)
1044   {
1045     return boost::asio::require(*static_cast<const Ex*>(ex),
1046         *static_cast<const Prop*>(prop));
1047   }
1048 
1049   template <typename Poly, typename Ex, class Prop>
1050   static Poly require_fn_impl(const void*, const void*, ...)
1051   {
1052     return Poly();
1053   }
1054 
1055   template <typename Poly, typename Ex, class Prop>
1056   static Poly require_fn(const void* ex, const void* prop)
1057   {
1058     return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1059   }
1060 
1061   template <typename Poly, typename Ex, class Prop>
1062   static Poly prefer_fn_impl(const void*, const void*,
1063       typename enable_if<
1064         is_same<Ex, void>::value
1065       >::type*)
1066   {
1067     bad_executor ex;
1068     boost::asio::detail::throw_exception(ex);
1069     return Poly();
1070   }
1071 
1072   template <typename Poly, typename Ex, class Prop>
1073   static Poly prefer_fn_impl(const void* ex, const void* prop,
1074       typename enable_if<
1075         !is_same<Ex, void>::value && Prop::is_preferable
1076       >::type*)
1077   {
1078     return boost::asio::prefer(*static_cast<const Ex*>(ex),
1079         *static_cast<const Prop*>(prop));
1080   }
1081 
1082   template <typename Poly, typename Ex, class Prop>
1083   static Poly prefer_fn_impl(const void*, const void*, ...)
1084   {
1085     return Poly();
1086   }
1087 
1088   template <typename Poly, typename Ex, class Prop>
1089   static Poly prefer_fn(const void* ex, const void* prop)
1090   {
1091     return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0);
1092   }
1093 
1094   template <typename Poly>
1095   struct prop_fns
1096   {
1097     void (*query)(void*, const void*, const void*);
1098     Poly (*require)(const void*, const void*);
1099     Poly (*prefer)(const void*, const void*);
1100   };
1101 
1102 #if defined(BOOST_ASIO_MSVC)
1103 # pragma warning (pop)
1104 #endif // defined(BOOST_ASIO_MSVC)
1105 
1106 private:
1107   template <typename Executor>
1108   static execution::blocking_t query_blocking(const Executor& ex, true_type)
1109   {
1110     return boost::asio::query(ex, execution::blocking);
1111   }
1112 
1113   template <typename Executor>
1114   static execution::blocking_t query_blocking(const Executor&, false_type)
1115   {
1116     return execution::blocking_t();
1117   }
1118 
1119   template <typename Executor>
1120   void construct_object(Executor& ex, true_type)
1121   {
1122     object_fns_ = object_fns_table<Executor>();
1123     target_ = new (&object_) Executor(BOOST_ASIO_MOVE_CAST(Executor)(ex));
1124   }
1125 
1126   template <typename Executor>
1127   void construct_object(Executor& ex, false_type)
1128   {
1129     object_fns_ = object_fns_table<boost::asio::detail::shared_ptr<void> >();
1130     boost::asio::detail::shared_ptr<Executor> p =
1131       boost::asio::detail::make_shared<Executor>(
1132           BOOST_ASIO_MOVE_CAST(Executor)(ex));
1133     target_ = p.get();
1134     new (&object_) boost::asio::detail::shared_ptr<void>(
1135         BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr<Executor>)(p));
1136   }
1137 
1138 /*private:*/public:
1139 //  template <typename...> friend class any_executor;
1140 
1141   typedef aligned_storage<
1142       sizeof(boost::asio::detail::shared_ptr<void>),
1143       alignment_of<boost::asio::detail::shared_ptr<void> >::value
1144     >::type object_type;
1145 
1146   object_type object_;
1147   const object_fns* object_fns_;
1148   void* target_;
1149   const target_fns* target_fns_;
1150 };
1151 
1152 template <typename Derived, typename Property, typename = void>
1153 struct any_executor_context
1154 {
1155 };
1156 
1157 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1158 
1159 template <typename Derived, typename Property>
1160 struct any_executor_context<Derived, Property,
1161     typename enable_if<Property::value>::type>
1162 {
1163   typename Property::query_result_type context() const
1164   {
1165     return static_cast<const Derived*>(this)->query(typename Property::type());
1166   }
1167 };
1168 
1169 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
1170 
1171 } // namespace detail
1172 
1173 template <>
1174 class any_executor<> : public detail::any_executor_base
1175 {
1176 public:
1177   any_executor() BOOST_ASIO_NOEXCEPT
1178     : detail::any_executor_base()
1179   {
1180   }
1181 
1182   any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1183     : detail::any_executor_base()
1184   {
1185   }
1186 
1187   template <typename Executor>
1188   any_executor(Executor ex,
1189       typename enable_if<
1190         conditional<
1191           !is_same<Executor, any_executor>::value
1192             && !is_base_of<detail::any_executor_base, Executor>::value,
1193           is_executor<Executor>,
1194           false_type
1195         >::type::value
1196       >::type* = 0)
1197     : detail::any_executor_base(
1198         BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type())
1199   {
1200   }
1201 
1202 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1203 
1204   template <typename... OtherSupportableProperties>
1205   any_executor(any_executor<OtherSupportableProperties...> other)
1206     : detail::any_executor_base(
1207         static_cast<const detail::any_executor_base&>(other))
1208   {
1209   }
1210 
1211 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1212 
1213   template <typename U0, typename U1, typename U2, typename U3,
1214       typename U4, typename U5, typename U6, typename U7>
1215   any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other)
1216     : detail::any_executor_base(
1217         static_cast<const detail::any_executor_base&>(other))
1218   {
1219   }
1220 
1221 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1222 
1223   any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1224     : detail::any_executor_base(
1225         static_cast<const detail::any_executor_base&>(other))
1226   {
1227   }
1228 
1229   any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1230   {
1231     if (this != &other)
1232     {
1233       detail::any_executor_base::operator=(
1234           static_cast<const detail::any_executor_base&>(other));
1235     }
1236     return *this;
1237   }
1238 
1239   any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1240   {
1241     detail::any_executor_base::operator=(p);
1242     return *this;
1243   }
1244 
1245 #if defined(BOOST_ASIO_HAS_MOVE)
1246 
1247   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1248     : detail::any_executor_base(
1249         static_cast<any_executor_base&&>(
1250           static_cast<any_executor_base&>(other)))
1251   {
1252   }
1253 
1254   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1255   {
1256     if (this != &other)
1257     {
1258       detail::any_executor_base::operator=(
1259           static_cast<detail::any_executor_base&&>(
1260             static_cast<detail::any_executor_base&>(other)));
1261     }
1262     return *this;
1263   }
1264 
1265 #endif // defined(BOOST_ASIO_HAS_MOVE)
1266 
1267   void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1268   {
1269     detail::any_executor_base::swap(
1270         static_cast<detail::any_executor_base&>(other));
1271   }
1272 
1273   using detail::any_executor_base::execute;
1274   using detail::any_executor_base::target;
1275   using detail::any_executor_base::target_type;
1276   using detail::any_executor_base::operator unspecified_bool_type;
1277   using detail::any_executor_base::operator!;
1278 
1279   bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1280   {
1281     return any_executor_base::equality_helper(other);
1282   }
1283 };
1284 
1285 inline bool operator==(const any_executor<>& a,
1286     const any_executor<>& b) BOOST_ASIO_NOEXCEPT
1287 {
1288   return a.equality_helper(b);
1289 }
1290 
1291 inline bool operator==(const any_executor<>& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1292 {
1293   return !a;
1294 }
1295 
1296 inline bool operator==(nullptr_t, const any_executor<>& b) BOOST_ASIO_NOEXCEPT
1297 {
1298   return !b;
1299 }
1300 
1301 inline bool operator!=(const any_executor<>& a,
1302     const any_executor<>& b) BOOST_ASIO_NOEXCEPT
1303 {
1304   return !a.equality_helper(b);
1305 }
1306 
1307 inline bool operator!=(const any_executor<>& a, nullptr_t) BOOST_ASIO_NOEXCEPT
1308 {
1309   return !!a;
1310 }
1311 
1312 inline bool operator!=(nullptr_t, const any_executor<>& b) BOOST_ASIO_NOEXCEPT
1313 {
1314   return !!b;
1315 }
1316 
1317 inline void swap(any_executor<>& a, any_executor<>& b) BOOST_ASIO_NOEXCEPT
1318 {
1319   return a.swap(b);
1320 }
1321 
1322 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1323 
1324 template <typename... SupportableProperties>
1325 class any_executor :
1326   public detail::any_executor_base,
1327   public detail::any_executor_context<
1328     any_executor<SupportableProperties...>,
1329       typename detail::supportable_properties<
1330         0, void(SupportableProperties...)>::find_context_as_property>
1331 {
1332 public:
1333   any_executor() BOOST_ASIO_NOEXCEPT
1334     : detail::any_executor_base(),
1335       prop_fns_(prop_fns_table<void>())
1336   {
1337   }
1338 
1339   any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT
1340     : detail::any_executor_base(),
1341       prop_fns_(prop_fns_table<void>())
1342   {
1343   }
1344 
1345   template <typename Executor>
1346   any_executor(Executor ex,
1347       typename enable_if<
1348         conditional<
1349           !is_same<Executor, any_executor>::value
1350             && !is_base_of<detail::any_executor_base, Executor>::value,
1351           detail::is_valid_target_executor<
1352             Executor, void(SupportableProperties...)>,
1353           false_type
1354         >::type::value
1355       >::type* = 0)
1356     : detail::any_executor_base(
1357         BOOST_ASIO_MOVE_CAST(Executor)(ex), false_type()),
1358       prop_fns_(prop_fns_table<Executor>())
1359   {
1360   }
1361 
1362   template <typename... OtherSupportableProperties>
1363   any_executor(any_executor<OtherSupportableProperties...> other,
1364       typename enable_if<
1365         conditional<
1366           !is_same<
1367             any_executor<OtherSupportableProperties...>,
1368             any_executor
1369           >::value,
1370           typename detail::supportable_properties<
1371             0, void(SupportableProperties...)>::template is_valid_target<
1372               any_executor<OtherSupportableProperties...> >,
1373           false_type
1374         >::type::value
1375       >::type* = 0)
1376     : detail::any_executor_base(BOOST_ASIO_MOVE_CAST(
1377           any_executor<OtherSupportableProperties...>)(other), true_type()),
1378       prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())
1379   {
1380   }
1381 
1382   any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT
1383     : detail::any_executor_base(
1384         static_cast<const detail::any_executor_base&>(other)),
1385       prop_fns_(other.prop_fns_)
1386   {
1387   }
1388 
1389   any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT
1390   {
1391     if (this != &other)
1392     {
1393       prop_fns_ = other.prop_fns_;
1394       detail::any_executor_base::operator=(
1395           static_cast<const detail::any_executor_base&>(other));
1396     }
1397     return *this;
1398   }
1399 
1400   any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT
1401   {
1402     prop_fns_ = prop_fns_table<void>();
1403     detail::any_executor_base::operator=(p);
1404     return *this;
1405   }
1406 
1407 #if defined(BOOST_ASIO_HAS_MOVE)
1408 
1409   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT
1410     : detail::any_executor_base(
1411         static_cast<any_executor_base&&>(
1412           static_cast<any_executor_base&>(other))),
1413       prop_fns_(other.prop_fns_)
1414   {
1415     other.prop_fns_ = prop_fns_table<void>();
1416   }
1417 
1418   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT
1419   {
1420     if (this != &other)
1421     {
1422       prop_fns_ = other.prop_fns_;
1423       detail::any_executor_base::operator=(
1424           static_cast<detail::any_executor_base&&>(
1425             static_cast<detail::any_executor_base&>(other)));
1426     }
1427     return *this;
1428   }
1429 
1430 #endif // defined(BOOST_ASIO_HAS_MOVE)
1431 
1432   void swap(any_executor& other) BOOST_ASIO_NOEXCEPT
1433   {
1434     if (this != &other)
1435     {
1436       detail::any_executor_base::swap(
1437           static_cast<detail::any_executor_base&>(other));
1438       const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_;
1439       other.prop_fns_ = prop_fns_;
1440       prop_fns_ = tmp_prop_fns;
1441     }
1442   }
1443 
1444   using detail::any_executor_base::execute;
1445   using detail::any_executor_base::target;
1446   using detail::any_executor_base::target_type;
1447   using detail::any_executor_base::operator unspecified_bool_type;
1448   using detail::any_executor_base::operator!;
1449 
1450   bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT
1451   {
1452     return any_executor_base::equality_helper(other);
1453   }
1454 
1455   template <typename T>
1456   struct find_convertible_property :
1457       detail::supportable_properties<
1458         0, void(SupportableProperties...)>::template
1459           find_convertible_property<T> {};
1460 
1461   template <typename Property>
1462   void query(const Property& p,
1463       typename enable_if<
1464         is_same<
1465           typename find_convertible_property<Property>::query_result_type,
1466           void
1467         >::value
1468       >::type* = 0) const
1469   {
1470     typedef find_convertible_property<Property> found;
1471     prop_fns_[found::index].query(0, object_fns_->target(*this),
1472         &static_cast<const typename found::type&>(p));
1473   }
1474 
1475   template <typename Property>
1476   typename find_convertible_property<Property>::query_result_type
1477   query(const Property& p,
1478       typename enable_if<
1479         !is_same<
1480           typename find_convertible_property<Property>::query_result_type,
1481           void
1482         >::value
1483         &&
1484         is_reference<
1485           typename find_convertible_property<Property>::query_result_type
1486         >::value
1487       >::type* = 0) const
1488   {
1489     typedef find_convertible_property<Property> found;
1490     typename remove_reference<
1491       typename found::query_result_type>::type* result = 0;
1492     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1493         &static_cast<const typename found::type&>(p));
1494     return *result;
1495   }
1496 
1497   template <typename Property>
1498   typename find_convertible_property<Property>::query_result_type
1499   query(const Property& p,
1500       typename enable_if<
1501         !is_same<
1502           typename find_convertible_property<Property>::query_result_type,
1503           void
1504         >::value
1505         &&
1506         is_scalar<
1507           typename find_convertible_property<Property>::query_result_type
1508         >::value
1509       >::type* = 0) const
1510   {
1511     typedef find_convertible_property<Property> found;
1512     typename found::query_result_type result;
1513     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1514         &static_cast<const typename found::type&>(p));
1515     return result;
1516   }
1517 
1518   template <typename Property>
1519   typename find_convertible_property<Property>::query_result_type
1520   query(const Property& p,
1521       typename enable_if<
1522         !is_same<
1523           typename find_convertible_property<Property>::query_result_type,
1524           void
1525         >::value
1526         &&
1527         !is_reference<
1528           typename find_convertible_property<Property>::query_result_type
1529         >::value
1530         &&
1531         !is_scalar<
1532           typename find_convertible_property<Property>::query_result_type
1533         >::value
1534       >::type* = 0) const
1535   {
1536     typedef find_convertible_property<Property> found;
1537     typename found::query_result_type* result;
1538     prop_fns_[found::index].query(&result, object_fns_->target(*this),
1539         &static_cast<const typename found::type&>(p));
1540     return *boost::asio::detail::scoped_ptr<
1541       typename found::query_result_type>(result);
1542   }
1543 
1544   template <typename T>
1545   struct find_convertible_requirable_property :
1546       detail::supportable_properties<
1547         0, void(SupportableProperties...)>::template
1548           find_convertible_requirable_property<T> {};
1549 
1550   template <typename Property>
1551   any_executor require(const Property& p,
1552       typename enable_if<
1553         find_convertible_requirable_property<Property>::value
1554       >::type* = 0) const
1555   {
1556     typedef find_convertible_requirable_property<Property> found;
1557     return prop_fns_[found::index].require(object_fns_->target(*this),
1558         &static_cast<const typename found::type&>(p));
1559   }
1560 
1561   template <typename T>
1562   struct find_convertible_preferable_property :
1563       detail::supportable_properties<
1564         0, void(SupportableProperties...)>::template
1565           find_convertible_preferable_property<T> {};
1566 
1567   template <typename Property>
1568   any_executor prefer(const Property& p,
1569       typename enable_if<
1570         find_convertible_preferable_property<Property>::value
1571       >::type* = 0) const
1572   {
1573     typedef find_convertible_preferable_property<Property> found;
1574     return prop_fns_[found::index].prefer(object_fns_->target(*this),
1575         &static_cast<const typename found::type&>(p));
1576   }
1577 
1578 //private:
1579   template <typename Ex>
1580   static const prop_fns<any_executor>* prop_fns_table()
1581   {
1582     static const prop_fns<any_executor> fns[] =
1583     {
1584       {
1585         &detail::any_executor_base::query_fn<
1586             Ex, SupportableProperties>,
1587         &detail::any_executor_base::require_fn<
1588             any_executor, Ex, SupportableProperties>,
1589         &detail::any_executor_base::prefer_fn<
1590             any_executor, Ex, SupportableProperties>
1591       }...
1592     };
1593     return fns;
1594   }
1595 
1596   const prop_fns<any_executor>* prop_fns_;
1597 };
1598 
1599 template <typename... SupportableProperties>
1600 inline bool operator==(const any_executor<SupportableProperties...>& a,
1601     const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1602 {
1603   return a.equality_helper(b);
1604 }
1605 
1606 template <typename... SupportableProperties>
1607 inline bool operator==(const any_executor<SupportableProperties...>& a,
1608     nullptr_t) BOOST_ASIO_NOEXCEPT
1609 {
1610   return !a;
1611 }
1612 
1613 template <typename... SupportableProperties>
1614 inline bool operator==(nullptr_t,
1615     const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1616 {
1617   return !b;
1618 }
1619 
1620 template <typename... SupportableProperties>
1621 inline bool operator!=(const any_executor<SupportableProperties...>& a,
1622     const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1623 {
1624   return !a.equality_helper(b);
1625 }
1626 
1627 template <typename... SupportableProperties>
1628 inline bool operator!=(const any_executor<SupportableProperties...>& a,
1629     nullptr_t) BOOST_ASIO_NOEXCEPT
1630 {
1631   return !!a;
1632 }
1633 
1634 template <typename... SupportableProperties>
1635 inline bool operator!=(nullptr_t,
1636     const any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1637 {
1638   return !!b;
1639 }
1640 
1641 template <typename... SupportableProperties>
1642 inline void swap(any_executor<SupportableProperties...>& a,
1643     any_executor<SupportableProperties...>& b) BOOST_ASIO_NOEXCEPT
1644 {
1645   return a.swap(b);
1646 }
1647 
1648 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
1649 
1650 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
1651   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n
1652 
1653 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \
1654   {  \
1655     &detail::any_executor_base::query_fn<Ex, T1>, \
1656     &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \
1657     &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \
1658   }
1659 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \
1660   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \
1661   { \
1662     &detail::any_executor_base::query_fn<Ex, T2>, \
1663     &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \
1664     &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \
1665   }
1666 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \
1667   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \
1668   { \
1669     &detail::any_executor_base::query_fn<Ex, T3>, \
1670     &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \
1671     &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \
1672   }
1673 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \
1674   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \
1675   { \
1676     &detail::any_executor_base::query_fn<Ex, T4>, \
1677     &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \
1678     &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \
1679   }
1680 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \
1681   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \
1682   { \
1683     &detail::any_executor_base::query_fn<Ex, T5>, \
1684     &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \
1685     &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \
1686   }
1687 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \
1688   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \
1689   { \
1690     &detail::any_executor_base::query_fn<Ex, T6>, \
1691     &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \
1692     &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \
1693   }
1694 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \
1695   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \
1696   { \
1697     &detail::any_executor_base::query_fn<Ex, T7>, \
1698     &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \
1699     &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \
1700   }
1701 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \
1702   BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \
1703   { \
1704     &detail::any_executor_base::query_fn<Ex, T8>, \
1705     &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \
1706     &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \
1707   }
1708 
1709 #if defined(BOOST_ASIO_HAS_MOVE)
1710 
1711 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1712   any_executor(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1713     : detail::any_executor_base( \
1714         static_cast<any_executor_base&&>( \
1715           static_cast<any_executor_base&>(other))), \
1716       prop_fns_(other.prop_fns_) \
1717   { \
1718     other.prop_fns_ = prop_fns_table<void>(); \
1719   } \
1720   \
1721   any_executor& operator=(any_executor&& other) BOOST_ASIO_NOEXCEPT \
1722   { \
1723     if (this != &other) \
1724     { \
1725       prop_fns_ = other.prop_fns_; \
1726       detail::any_executor_base::operator=( \
1727           static_cast<detail::any_executor_base&&>( \
1728             static_cast<detail::any_executor_base&>(other))); \
1729     } \
1730     return *this; \
1731   } \
1732   /**/
1733 #else // defined(BOOST_ASIO_HAS_MOVE)
1734 
1735 # define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
1736 
1737 #endif // defined(BOOST_ASIO_HAS_MOVE)
1738 
1739 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \
1740   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
1741   class any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> : \
1742     public detail::any_executor_base, \
1743     public detail::any_executor_context< \
1744       any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, \
1745         typename detail::supportable_properties< \
1746           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \
1747   { \
1748   public: \
1749     any_executor() BOOST_ASIO_NOEXCEPT \
1750       : detail::any_executor_base(), \
1751         prop_fns_(prop_fns_table<void>()) \
1752     { \
1753     } \
1754     \
1755     any_executor(nullptr_t) BOOST_ASIO_NOEXCEPT \
1756       : detail::any_executor_base(), \
1757         prop_fns_(prop_fns_table<void>()) \
1758     { \
1759     } \
1760     \
1761     template <BOOST_ASIO_EXECUTION_EXECUTOR Executor> \
1762     any_executor(Executor ex, \
1763         typename enable_if< \
1764           conditional< \
1765             !is_same<Executor, any_executor>::value \
1766               && !is_base_of<detail::any_executor_base, Executor>::value, \
1767             detail::is_valid_target_executor< \
1768               Executor, void(BOOST_ASIO_VARIADIC_TARGS(n))>, \
1769             false_type \
1770           >::type::value \
1771         >::type* = 0) \
1772       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1773             Executor)(ex), false_type()), \
1774         prop_fns_(prop_fns_table<Executor>()) \
1775     { \
1776     } \
1777     \
1778     any_executor(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1779       : detail::any_executor_base( \
1780           static_cast<const detail::any_executor_base&>(other)), \
1781         prop_fns_(other.prop_fns_) \
1782     { \
1783     } \
1784     \
1785     any_executor(any_executor<> other) \
1786       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1787             any_executor<>)(other), true_type()), \
1788         prop_fns_(prop_fns_table<any_executor<> >()) \
1789     { \
1790     } \
1791     \
1792     template <typename OtherAnyExecutor> \
1793     any_executor(OtherAnyExecutor other, \
1794         typename enable_if< \
1795           conditional< \
1796             !is_same<OtherAnyExecutor, any_executor>::value \
1797               && is_base_of<detail::any_executor_base, \
1798                 OtherAnyExecutor>::value, \
1799             typename detail::supportable_properties< \
1800               0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1801                 is_valid_target<OtherAnyExecutor>, \
1802             false_type \
1803           >::type::value \
1804         >::type* = 0) \
1805       : detail::any_executor_base(BOOST_ASIO_MOVE_CAST( \
1806             OtherAnyExecutor)(other), true_type()), \
1807         prop_fns_(prop_fns_table<OtherAnyExecutor>()) \
1808     { \
1809     } \
1810     \
1811     any_executor& operator=(const any_executor& other) BOOST_ASIO_NOEXCEPT \
1812     { \
1813       if (this != &other) \
1814       { \
1815         prop_fns_ = other.prop_fns_; \
1816         detail::any_executor_base::operator=( \
1817             static_cast<const detail::any_executor_base&>(other)); \
1818       } \
1819       return *this; \
1820     } \
1821     \
1822     any_executor& operator=(nullptr_t p) BOOST_ASIO_NOEXCEPT \
1823     { \
1824       prop_fns_ = prop_fns_table<void>(); \
1825       detail::any_executor_base::operator=(p); \
1826       return *this; \
1827     } \
1828     \
1829     BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \
1830     \
1831     void swap(any_executor& other) BOOST_ASIO_NOEXCEPT \
1832     { \
1833       if (this != &other) \
1834       { \
1835         detail::any_executor_base::swap( \
1836             static_cast<detail::any_executor_base&>(other)); \
1837         const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \
1838         other.prop_fns_ = prop_fns_; \
1839         prop_fns_ = tmp_prop_fns; \
1840       } \
1841     } \
1842     \
1843     using detail::any_executor_base::execute; \
1844     using detail::any_executor_base::target; \
1845     using detail::any_executor_base::target_type; \
1846     using detail::any_executor_base::operator unspecified_bool_type; \
1847     using detail::any_executor_base::operator!; \
1848     \
1849     bool equality_helper(const any_executor& other) const BOOST_ASIO_NOEXCEPT \
1850     { \
1851       return any_executor_base::equality_helper(other); \
1852     } \
1853     \
1854     template <typename T> \
1855     struct find_convertible_property : \
1856         detail::supportable_properties< \
1857           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1858             find_convertible_property<T> {}; \
1859     \
1860     template <typename Property> \
1861     void query(const Property& p, \
1862         typename enable_if< \
1863           is_same< \
1864             typename find_convertible_property<Property>::query_result_type, \
1865             void \
1866           >::value \
1867         >::type* = 0) const \
1868     { \
1869       typedef find_convertible_property<Property> found; \
1870       prop_fns_[found::index].query(0, object_fns_->target(*this), \
1871           &static_cast<const typename found::type&>(p)); \
1872     } \
1873     \
1874     template <typename Property> \
1875     typename find_convertible_property<Property>::query_result_type \
1876     query(const Property& p, \
1877         typename enable_if< \
1878           !is_same< \
1879             typename find_convertible_property<Property>::query_result_type, \
1880             void \
1881           >::value \
1882           && \
1883           is_reference< \
1884             typename find_convertible_property<Property>::query_result_type \
1885           >::value \
1886         >::type* = 0) const \
1887     { \
1888       typedef find_convertible_property<Property> found; \
1889       typename remove_reference< \
1890         typename found::query_result_type>::type* result; \
1891       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
1892           &static_cast<const typename found::type&>(p)); \
1893       return *result; \
1894     } \
1895     \
1896     template <typename Property> \
1897     typename find_convertible_property<Property>::query_result_type \
1898     query(const Property& p, \
1899         typename enable_if< \
1900           !is_same< \
1901             typename find_convertible_property<Property>::query_result_type, \
1902             void \
1903           >::value \
1904           && \
1905           is_scalar< \
1906             typename find_convertible_property<Property>::query_result_type \
1907           >::value \
1908         >::type* = 0) const \
1909     { \
1910       typedef find_convertible_property<Property> found; \
1911       typename found::query_result_type result; \
1912       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
1913           &static_cast<const typename found::type&>(p)); \
1914       return result; \
1915     } \
1916     \
1917     template <typename Property> \
1918     typename find_convertible_property<Property>::query_result_type \
1919     query(const Property& p, \
1920         typename enable_if< \
1921           !is_same< \
1922             typename find_convertible_property<Property>::query_result_type, \
1923             void \
1924           >::value \
1925           && \
1926           !is_reference< \
1927             typename find_convertible_property<Property>::query_result_type \
1928           >::value \
1929           && \
1930           !is_scalar< \
1931             typename find_convertible_property<Property>::query_result_type \
1932           >::value \
1933         >::type* = 0) const \
1934     { \
1935       typedef find_convertible_property<Property> found; \
1936       typename found::query_result_type* result; \
1937       prop_fns_[found::index].query(&result, object_fns_->target(*this), \
1938           &static_cast<const typename found::type&>(p)); \
1939       return *boost::asio::detail::scoped_ptr< \
1940         typename found::query_result_type>(result); \
1941     } \
1942     \
1943     template <typename T> \
1944     struct find_convertible_requirable_property : \
1945         detail::supportable_properties< \
1946           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1947             find_convertible_requirable_property<T> {}; \
1948     \
1949     template <typename Property> \
1950     any_executor require(const Property& p, \
1951         typename enable_if< \
1952           find_convertible_requirable_property<Property>::value \
1953         >::type* = 0) const \
1954     { \
1955       typedef find_convertible_requirable_property<Property> found; \
1956       return prop_fns_[found::index].require(object_fns_->target(*this), \
1957           &static_cast<const typename found::type&>(p)); \
1958     } \
1959     \
1960     template <typename T> \
1961     struct find_convertible_preferable_property : \
1962         detail::supportable_properties< \
1963           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
1964             find_convertible_preferable_property<T> {}; \
1965     \
1966     template <typename Property> \
1967     any_executor prefer(const Property& p, \
1968         typename enable_if< \
1969           find_convertible_preferable_property<Property>::value \
1970         >::type* = 0) const \
1971     { \
1972       typedef find_convertible_preferable_property<Property> found; \
1973       return prop_fns_[found::index].prefer(object_fns_->target(*this), \
1974           &static_cast<const typename found::type&>(p)); \
1975     } \
1976     \
1977     template <typename Ex> \
1978     static const prop_fns<any_executor>* prop_fns_table() \
1979     { \
1980       static const prop_fns<any_executor> fns[] = \
1981       { \
1982         BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \
1983       }; \
1984       return fns; \
1985     } \
1986     \
1987     const prop_fns<any_executor>* prop_fns_; \
1988     typedef detail::supportable_properties<0, \
1989         void(BOOST_ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \
1990   }; \
1991   \
1992   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
1993   inline bool operator==(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
1994       const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
1995   { \
1996     return a.equality_helper(b); \
1997   } \
1998   \
1999   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2000   inline bool operator==(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2001       nullptr_t) BOOST_ASIO_NOEXCEPT \
2002   { \
2003     return !a; \
2004   } \
2005   \
2006   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2007   inline bool operator==(nullptr_t, \
2008       const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2009   { \
2010     return !b; \
2011   } \
2012   \
2013   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2014   inline bool operator!=(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2015       const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2016   { \
2017     return !a.equality_helper(b); \
2018   } \
2019   \
2020   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2021   inline bool operator!=(const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2022       nullptr_t) BOOST_ASIO_NOEXCEPT \
2023   { \
2024     return !!a; \
2025   } \
2026   \
2027   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2028   inline bool operator!=(nullptr_t, \
2029       const any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2030   { \
2031     return !!b; \
2032   } \
2033   \
2034   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2035   inline void swap(any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& a, \
2036       any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>& b) BOOST_ASIO_NOEXCEPT \
2037   { \
2038     return a.swap(b); \
2039   } \
2040   /**/
2041   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF)
2042 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_DEF
2043 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS
2044 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS
2045 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1
2046 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2
2047 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3
2048 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4
2049 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5
2050 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6
2051 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7
2052 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8
2053 
2054 #endif // if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2055 
2056 } // namespace execution
2057 namespace traits {
2058 
2059 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2060 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2061 
2062 template <typename... SupportableProperties>
2063 struct equality_comparable<execution::any_executor<SupportableProperties...> >
2064 {
2065   static const bool is_valid = true;
2066   static const bool is_noexcept = true;
2067 };
2068 
2069 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2070 
2071 template <>
2072 struct equality_comparable<execution::any_executor<> >
2073 {
2074   static const bool is_valid = true;
2075   static const bool is_noexcept = true;
2076 };
2077 
2078 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \
2079   template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2080   struct equality_comparable< \
2081       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> > \
2082   { \
2083     static const bool is_valid = true; \
2084     static const bool is_noexcept = true; \
2085   }; \
2086   /**/
2087   BOOST_ASIO_VARIADIC_GENERATE(
2088       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF)
2089 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF
2090 
2091 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2092 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
2093 
2094 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2095 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2096 
2097 template <typename F, typename... SupportableProperties>
2098 struct execute_member<execution::any_executor<SupportableProperties...>, F>
2099 {
2100   static const bool is_valid = true;
2101   static const bool is_noexcept = false;
2102   typedef void result_type;
2103 };
2104 
2105 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2106 
2107 template <typename F>
2108 struct execute_member<execution::any_executor<>, F>
2109 {
2110   static const bool is_valid = true;
2111   static const bool is_noexcept = false;
2112   typedef void result_type;
2113 };
2114 
2115 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \
2116   template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2117   struct execute_member< \
2118       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, F> \
2119   { \
2120     static const bool is_valid = true; \
2121     static const bool is_noexcept = false; \
2122     typedef void result_type; \
2123   }; \
2124   /**/
2125   BOOST_ASIO_VARIADIC_GENERATE(
2126       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF)
2127 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF
2128 
2129 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2130 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
2131 
2132 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2133 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2134 
2135 template <typename Prop, typename... SupportableProperties>
2136 struct query_member<
2137     execution::any_executor<SupportableProperties...>, Prop,
2138     typename enable_if<
2139       execution::detail::supportable_properties<
2140         0, void(SupportableProperties...)>::template
2141           find_convertible_property<Prop>::value
2142     >::type>
2143 {
2144   static const bool is_valid = true;
2145   static const bool is_noexcept = false;
2146   typedef typename execution::detail::supportable_properties<
2147       0, void(SupportableProperties...)>::template
2148         find_convertible_property<Prop>::query_result_type result_type;
2149 };
2150 
2151 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2152 
2153 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \
2154   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2155   struct query_member< \
2156       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2157       typename enable_if< \
2158         execution::detail::supportable_properties< \
2159           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2160             find_convertible_property<Prop>::value \
2161     >::type> \
2162   { \
2163     static const bool is_valid = true; \
2164     static const bool is_noexcept = false; \
2165     typedef typename execution::detail::supportable_properties< \
2166         0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2167           find_convertible_property<Prop>::query_result_type result_type; \
2168   }; \
2169   /**/
2170   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF)
2171 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF
2172 
2173 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2174 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
2175 
2176 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2177 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2178 
2179 template <typename Prop, typename... SupportableProperties>
2180 struct require_member<
2181     execution::any_executor<SupportableProperties...>, Prop,
2182     typename enable_if<
2183       execution::detail::supportable_properties<
2184         0, void(SupportableProperties...)>::template
2185           find_convertible_requirable_property<Prop>::value
2186     >::type>
2187 {
2188   static const bool is_valid = true;
2189   static const bool is_noexcept = false;
2190   typedef execution::any_executor<SupportableProperties...> result_type;
2191 };
2192 
2193 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2194 
2195 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \
2196   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2197   struct require_member< \
2198       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2199       typename enable_if< \
2200         execution::detail::supportable_properties< \
2201           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2202             find_convertible_requirable_property<Prop>::value \
2203       >::type> \
2204   { \
2205     static const bool is_valid = true; \
2206     static const bool is_noexcept = false; \
2207     typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2208   }; \
2209   /**/
2210   BOOST_ASIO_VARIADIC_GENERATE(
2211       BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF)
2212 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF
2213 
2214 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2215 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
2216 
2217 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2218 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2219 
2220 template <typename Prop, typename... SupportableProperties>
2221 struct prefer_member<
2222     execution::any_executor<SupportableProperties...>, Prop,
2223     typename enable_if<
2224       execution::detail::supportable_properties<
2225         0, void(SupportableProperties...)>::template
2226           find_convertible_preferable_property<Prop>::value
2227     >::type>
2228 {
2229   static const bool is_valid = true;
2230   static const bool is_noexcept = false;
2231   typedef execution::any_executor<SupportableProperties...> result_type;
2232 };
2233 
2234 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2235 
2236 #define BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \
2237   template <typename Prop, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
2238   struct prefer_member< \
2239       execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)>, Prop, \
2240       typename enable_if< \
2241         execution::detail::supportable_properties< \
2242           0, void(BOOST_ASIO_VARIADIC_TARGS(n))>::template \
2243             find_convertible_preferable_property<Prop>::value \
2244       >::type> \
2245   { \
2246     static const bool is_valid = true; \
2247     static const bool is_noexcept = false; \
2248     typedef execution::any_executor<BOOST_ASIO_VARIADIC_TARGS(n)> result_type; \
2249   }; \
2250   /**/
2251   BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF)
2252 #undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF
2253 
2254 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
2255 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
2256 
2257 } // namespace traits
2258 
2259 #endif // defined(GENERATING_DOCUMENTATION)
2260 
2261 } // namespace asio
2262 } // namespace boost
2263 
2264 #include <boost/asio/detail/pop_options.hpp>
2265 
2266 #endif // BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP
2267