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