// // execution/any_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef ASIO_EXECUTION_ANY_EXECUTOR_HPP #define ASIO_EXECUTION_ANY_EXECUTOR_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include #include #include "asio/detail/assert.hpp" #include "asio/detail/cstddef.hpp" #include "asio/detail/executor_function.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/scoped_ptr.hpp" #include "asio/detail/type_traits.hpp" #include "asio/detail/throw_exception.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/execution/bad_executor.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" #include "asio/prefer.hpp" #include "asio/query.hpp" #include "asio/require.hpp" #include "asio/detail/push_options.hpp" namespace asio { #if defined(GENERATING_DOCUMENTATION) namespace execution { /// Polymorphic executor wrapper. template class any_executor { public: /// Default constructor. any_executor() noexcept; /// Construct in an empty state. Equivalent effects to default constructor. any_executor(nullptr_t) noexcept; /// Copy constructor. any_executor(const any_executor& e) noexcept; /// Move constructor. any_executor(any_executor&& e) noexcept; /// Construct to point to the same target as another any_executor. template any_executor(any_executor e); /// Construct a polymorphic wrapper for the specified executor. template any_executor(Executor e); /// Assignment operator. any_executor& operator=(const any_executor& e) noexcept; /// Move assignment operator. any_executor& operator=(any_executor&& e) noexcept; /// Assignment operator that sets the polymorphic wrapper to the empty state. any_executor& operator=(nullptr_t); /// Assignment operator to create a polymorphic wrapper for the specified /// executor. template any_executor& operator=(Executor e); /// Destructor. ~any_executor(); /// Swap targets with another polymorphic wrapper. void swap(any_executor& other) noexcept; /// Obtain a polymorphic wrapper with the specified property. /** * Do not call this function directly. It is intended for use with the * asio::require and asio::prefer customisation points. * * For example: * @code execution::any_executor ex = ...; * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode */ template any_executor require(Property) const; /// Obtain a polymorphic wrapper with the specified property. /** * Do not call this function directly. It is intended for use with the * asio::prefer customisation point. * * For example: * @code execution::any_executor ex = ...; * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode */ template any_executor prefer(Property) const; /// Obtain the value associated with the specified property. /** * Do not call this function directly. It is intended for use with the * asio::query customisation point. * * For example: * @code execution::any_executor ex = ...; * size_t n = asio::query(ex, execution::occupancy); @endcode */ template typename Property::polymorphic_query_result_type query(Property) const; /// Execute the function on the target executor. /** * Do not call this function directly. It is intended for use with the * execution::execute customisation point. * * For example: * @code execution::any_executor<> ex = ...; * execution::execute(ex, my_function_object); @endcode * * Throws asio::bad_executor if the polymorphic wrapper has no target. */ template void execute(Function&& f) const; /// Obtain the underlying execution context. /** * This function is provided for backward compatibility. It is automatically * defined when the @c SupportableProperties... list includes a property of * type execution::context_as, for some type U. */ automatically_determined context() const; /// Determine whether the wrapper has a target executor. /** * @returns @c true if the polymorphic wrapper has a target executor, * otherwise false. */ explicit operator bool() const noexcept; /// Get the type of the target executor. const type_info& target_type() const noexcept; /// Get a pointer to the target executor. template Executor* target() noexcept; /// Get a pointer to the target executor. template const Executor* target() const noexcept; }; /// Equality operator. /** * @relates any_executor */ template bool operator==(const any_executor& a, const any_executor& b) noexcept; /// Equality operator. /** * @relates any_executor */ template bool operator==(const any_executor& a, nullptr_t) noexcept; /// Equality operator. /** * @relates any_executor */ template bool operator==(nullptr_t, const any_executor& b) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(const any_executor& a, const any_executor& b) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(const any_executor& a, nullptr_t) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(nullptr_t, const any_executor& b) noexcept; } // namespace execution #else // defined(GENERATING_DOCUMENTATION) namespace execution { #if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) #define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template class any_executor; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template class any_executor; #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) template struct context_as_t; namespace detail { // Traits used to detect whether a property is requirable or preferable, taking // into account that T::is_requirable or T::is_preferable may not not be well // formed. template struct is_requirable : false_type {}; template struct is_requirable::type> : true_type {}; template struct is_preferable : false_type {}; template struct is_preferable::type> : true_type {}; // Trait used to detect context_as property, for backward compatibility. template struct is_context_as : false_type {}; template struct is_context_as > : true_type {}; // Helper template to: // - Check if a target can supply the supportable properties. // - Find the first convertible-from-T property in the list. template struct supportable_properties; template struct supportable_properties { template struct is_valid_target : integral_constant::value ? can_require::value : true ) && ( is_preferable::value ? can_prefer::value : true ) && ( !is_requirable::value && !is_preferable::value ? can_query::value : true ) > { }; struct found { ASIO_STATIC_CONSTEXPR(bool, value = true); typedef Prop type; typedef typename Prop::polymorphic_query_result_type query_result_type; ASIO_STATIC_CONSTEXPR(std::size_t, index = I); }; struct not_found { ASIO_STATIC_CONSTEXPR(bool, value = false); }; template struct find_convertible_property : conditional< is_same::value || is_convertible::value, found, not_found >::type {}; template struct find_convertible_requirable_property : conditional< is_requirable::value && (is_same::value || is_convertible::value), found, not_found >::type {}; template struct find_convertible_preferable_property : conditional< is_preferable::value && (is_same::value || is_convertible::value), found, not_found >::type {}; struct find_context_as_property : conditional< is_context_as::value, found, not_found >::type {}; }; #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct supportable_properties { template struct is_valid_target : integral_constant::template is_valid_target::value && supportable_properties::template is_valid_target::value ) > { }; template struct find_convertible_property : conditional< is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_property >::type {}; template struct find_convertible_requirable_property : conditional< is_requirable::value && is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_requirable_property >::type {}; template struct find_convertible_preferable_property : conditional< is_preferable::value && is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_preferable_property >::type {}; struct find_context_as_property : conditional< is_context_as::value, typename supportable_properties::found, typename supportable_properties::find_context_as_property >::type {}; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \ template \ struct supportable_properties \ { \ template \ struct is_valid_target : integral_constant::template is_valid_target::value \ && \ supportable_properties::template \ is_valid_target::value \ ) \ > \ { \ }; \ \ template \ struct find_convertible_property : \ conditional< \ is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_property \ >::type {}; \ \ template \ struct find_convertible_requirable_property : \ conditional< \ is_requirable::value \ && is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_requirable_property \ >::type {}; \ \ template \ struct find_convertible_preferable_property : \ conditional< \ is_preferable::value \ && is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_preferable_property \ >::type {}; \ \ struct find_context_as_property : \ conditional< \ is_context_as::value, \ typename supportable_properties::found, \ typename supportable_properties::find_context_as_property \ >::type {}; \ }; \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct is_valid_target_executor : conditional< is_executor::value, typename supportable_properties<0, Props>::template is_valid_target, false_type >::type { }; class any_executor_base { public: any_executor_base() ASIO_NOEXCEPT : object_fns_(object_fns_table()), target_(0), target_fns_(target_fns_table()) { } template any_executor_base(Executor ex, false_type) : target_fns_(target_fns_table( any_executor_base::query_blocking(ex, can_query()) == execution::blocking.always)) { any_executor_base::construct_object(ex, integral_constant::value <= alignment_of::value >()); } template any_executor_base(Executor other, true_type) : object_fns_(object_fns_table >()), target_fns_(other.target_fns_) { asio::detail::shared_ptr p = asio::detail::make_shared( ASIO_MOVE_CAST(Executor)(other)); target_ = p->template target(); new (&object_) asio::detail::shared_ptr( ASIO_MOVE_CAST(asio::detail::shared_ptr)(p)); } any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT : object_fns_(other.object_fns_), target_fns_(other.target_fns_) { object_fns_->copy(*this, other); } ~any_executor_base() ASIO_NOEXCEPT { object_fns_->destroy(*this); } any_executor_base& operator=( const any_executor_base& other) ASIO_NOEXCEPT { if (this != &other) { object_fns_->destroy(*this); object_fns_ = other.object_fns_; target_fns_ = other.target_fns_; object_fns_->copy(*this, other); } return *this; } any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT { object_fns_->destroy(*this); target_ = 0; object_fns_ = object_fns_table(); target_fns_ = target_fns_table(); return *this; } #if defined(ASIO_HAS_MOVE) any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT : object_fns_(other.object_fns_), target_fns_(other.target_fns_) { other.object_fns_ = object_fns_table(); other.target_fns_ = target_fns_table(); object_fns_->move(*this, other); other.target_ = 0; } any_executor_base& operator=( any_executor_base&& other) ASIO_NOEXCEPT { if (this != &other) { object_fns_->destroy(*this); object_fns_ = other.object_fns_; other.object_fns_ = object_fns_table(); target_fns_ = other.target_fns_; other.target_fns_ = target_fns_table(); object_fns_->move(*this, other); other.target_ = 0; } return *this; } #endif // defined(ASIO_HAS_MOVE) void swap(any_executor_base& other) ASIO_NOEXCEPT { if (this != &other) { any_executor_base tmp(ASIO_MOVE_CAST(any_executor_base)(other)); other = ASIO_MOVE_CAST(any_executor_base)(*this); *this = ASIO_MOVE_CAST(any_executor_base)(tmp); } } template void execute(ASIO_MOVE_ARG(F) f) const { if (target_fns_->blocking_execute != 0) { asio::detail::non_const_lvalue f2(f); target_fns_->blocking_execute(*this, function_view(f2.value)); } else { target_fns_->execute(*this, function(ASIO_MOVE_CAST(F)(f), std::allocator())); } } template Executor* target() { return static_cast(target_); } template const Executor* target() const { return static_cast(target_); } const std::type_info& target_type() const { return target_fns_->target_type(); } struct unspecified_bool_type_t {}; typedef void (*unspecified_bool_type)(unspecified_bool_type_t); static void unspecified_bool_true(unspecified_bool_type_t) {} operator unspecified_bool_type() const ASIO_NOEXCEPT { return target_ ? &any_executor_base::unspecified_bool_true : 0; } bool operator!() const ASIO_NOEXCEPT { return target_ == 0; } protected: bool equality_helper(const any_executor_base& other) const ASIO_NOEXCEPT { if (target_ == other.target_) return true; if (target_ && !other.target_) return false; if (!target_ && other.target_) return false; if (target_fns_ != other.target_fns_) return false; return target_fns_->equal(*this, other); } template Ex& object() { return *static_cast(static_cast(&object_)); } template const Ex& object() const { return *static_cast(static_cast(&object_)); } struct object_fns { void (*destroy)(any_executor_base&); void (*copy)(any_executor_base&, const any_executor_base&); void (*move)(any_executor_base&, any_executor_base&); const void* (*target)(const any_executor_base&); }; static void destroy_void(any_executor_base&) { } static void copy_void(any_executor_base& ex1, const any_executor_base&) { ex1.target_ = 0; } static void move_void(any_executor_base& ex1, any_executor_base&) { ex1.target_ = 0; } static const void* target_void(const any_executor_base&) { return 0; } template static const object_fns* object_fns_table( typename enable_if< is_same::value >::type* = 0) { static const object_fns fns = { &any_executor_base::destroy_void, &any_executor_base::copy_void, &any_executor_base::move_void, &any_executor_base::target_void }; return &fns; } static void destroy_shared(any_executor_base& ex) { typedef asio::detail::shared_ptr type; ex.object().~type(); } static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) { typedef asio::detail::shared_ptr type; new (&ex1.object_) type(ex2.object()); ex1.target_ = ex2.target_; } static void move_shared(any_executor_base& ex1, any_executor_base& ex2) { typedef asio::detail::shared_ptr type; new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object())); ex1.target_ = ex2.target_; ex2.object().~type(); } static const void* target_shared(const any_executor_base& ex) { typedef asio::detail::shared_ptr type; return ex.object().get(); } template static const object_fns* object_fns_table( typename enable_if< is_same >::value >::type* = 0) { static const object_fns fns = { &any_executor_base::destroy_shared, &any_executor_base::copy_shared, &any_executor_base::move_shared, &any_executor_base::target_shared }; return &fns; } template static void destroy_object(any_executor_base& ex) { ex.object().~Obj(); } template static void copy_object(any_executor_base& ex1, const any_executor_base& ex2) { new (&ex1.object_) Obj(ex2.object()); ex1.target_ = &ex1.object(); } template static void move_object(any_executor_base& ex1, any_executor_base& ex2) { new (&ex1.object_) Obj(ASIO_MOVE_CAST(Obj)(ex2.object())); ex1.target_ = &ex1.object(); ex2.object().~Obj(); } template static const void* target_object(const any_executor_base& ex) { return &ex.object(); } template static const object_fns* object_fns_table( typename enable_if< !is_same::value && !is_same >::value >::type* = 0) { static const object_fns fns = { &any_executor_base::destroy_object, &any_executor_base::copy_object, &any_executor_base::move_object, &any_executor_base::target_object }; return &fns; } typedef asio::detail::executor_function function; typedef asio::detail::executor_function_view function_view; struct target_fns { const std::type_info& (*target_type)(); bool (*equal)(const any_executor_base&, const any_executor_base&); void (*execute)(const any_executor_base&, ASIO_MOVE_ARG(function)); void (*blocking_execute)(const any_executor_base&, function_view); }; static const std::type_info& target_type_void() { return typeid(void); } static bool equal_void(const any_executor_base&, const any_executor_base&) { return true; } static void execute_void(const any_executor_base&, ASIO_MOVE_ARG(function)) { bad_executor ex; asio::detail::throw_exception(ex); } static void blocking_execute_void(const any_executor_base&, function_view) { bad_executor ex; asio::detail::throw_exception(ex); } template static const target_fns* target_fns_table( typename enable_if< is_same::value >::type* = 0) { static const target_fns fns = { &any_executor_base::target_type_void, &any_executor_base::equal_void, &any_executor_base::execute_void, &any_executor_base::blocking_execute_void }; return &fns; } template static const std::type_info& target_type_ex() { return typeid(Ex); } template static bool equal_ex(const any_executor_base& ex1, const any_executor_base& ex2) { return *ex1.target() == *ex2.target(); } template static void execute_ex(const any_executor_base& ex, ASIO_MOVE_ARG(function) f) { execution::execute(*ex.target(), ASIO_MOVE_CAST(function)(f)); } template static void blocking_execute_ex(const any_executor_base& ex, function_view f) { execution::execute(*ex.target(), f); } template static const target_fns* target_fns_table(bool is_always_blocking, typename enable_if< !is_same::value >::type* = 0) { static const target_fns fns_with_execute = { &any_executor_base::target_type_ex, &any_executor_base::equal_ex, &any_executor_base::execute_ex, 0 }; static const target_fns fns_with_blocking_execute = { &any_executor_base::target_type_ex, &any_executor_base::equal_ex, 0, &any_executor_base::blocking_execute_ex }; return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute; } #if defined(ASIO_MSVC) # pragma warning (push) # pragma warning (disable:4702) #endif // defined(ASIO_MSVC) static void query_fn_void(void*, const void*, const void*) { bad_executor ex; asio::detail::throw_exception(ex); } template static void query_fn_non_void(void*, const void* ex, const void* prop, typename enable_if< asio::can_query::value && is_same::value >::type*) { asio::query(*static_cast(ex), *static_cast(prop)); } template static void query_fn_non_void(void*, const void*, const void*, typename enable_if< !asio::can_query::value && is_same::value >::type*) { } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && is_reference::value >::type*) { *static_cast::type**>(result) = &static_cast( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void*, const void*, const void*, typename enable_if< !asio::can_query::value && !is_same::value && is_reference::value >::type*) { std::terminate(); // Combination should not be possible. } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && is_scalar::value >::type*) { *static_cast(result) = static_cast( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void* result, const void*, const void*, typename enable_if< !asio::can_query::value && !is_same::value && is_scalar::value >::type*) { *static_cast(result) = typename Prop::polymorphic_query_result_type(); } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && !is_reference::value && !is_scalar::value >::type*) { *static_cast(result) = new typename Prop::polymorphic_query_result_type( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void* result, const void*, const void*, ...) { *static_cast(result) = new typename Prop::polymorphic_query_result_type(); } template static void query_fn_impl(void* result, const void* ex, const void* prop, typename enable_if< is_same::value >::type*) { query_fn_void(result, ex, prop); } template static void query_fn_impl(void* result, const void* ex, const void* prop, typename enable_if< !is_same::value >::type*) { query_fn_non_void(result, ex, prop, 0); } template static void query_fn(void* result, const void* ex, const void* prop) { query_fn_impl(result, ex, prop, 0); } template static Poly require_fn_impl(const void*, const void*, typename enable_if< is_same::value >::type*) { bad_executor ex; asio::detail::throw_exception(ex); return Poly(); } template static Poly require_fn_impl(const void* ex, const void* prop, typename enable_if< !is_same::value && Prop::is_requirable >::type*) { return asio::require(*static_cast(ex), *static_cast(prop)); } template static Poly require_fn_impl(const void*, const void*, ...) { return Poly(); } template static Poly require_fn(const void* ex, const void* prop) { return require_fn_impl(ex, prop, 0); } template static Poly prefer_fn_impl(const void*, const void*, typename enable_if< is_same::value >::type*) { bad_executor ex; asio::detail::throw_exception(ex); return Poly(); } template static Poly prefer_fn_impl(const void* ex, const void* prop, typename enable_if< !is_same::value && Prop::is_preferable >::type*) { return asio::prefer(*static_cast(ex), *static_cast(prop)); } template static Poly prefer_fn_impl(const void*, const void*, ...) { return Poly(); } template static Poly prefer_fn(const void* ex, const void* prop) { return prefer_fn_impl(ex, prop, 0); } template struct prop_fns { void (*query)(void*, const void*, const void*); Poly (*require)(const void*, const void*); Poly (*prefer)(const void*, const void*); }; #if defined(ASIO_MSVC) # pragma warning (pop) #endif // defined(ASIO_MSVC) private: template static execution::blocking_t query_blocking(const Executor& ex, true_type) { return asio::query(ex, execution::blocking); } template static execution::blocking_t query_blocking(const Executor&, false_type) { return execution::blocking_t(); } template void construct_object(Executor& ex, true_type) { object_fns_ = object_fns_table(); target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex)); } template void construct_object(Executor& ex, false_type) { object_fns_ = object_fns_table >(); asio::detail::shared_ptr p = asio::detail::make_shared( ASIO_MOVE_CAST(Executor)(ex)); target_ = p.get(); new (&object_) asio::detail::shared_ptr( ASIO_MOVE_CAST(asio::detail::shared_ptr)(p)); } /*private:*/public: // template friend class any_executor; typedef aligned_storage< sizeof(asio::detail::shared_ptr), alignment_of >::value >::type object_type; object_type object_; const object_fns* object_fns_; void* target_; const target_fns* target_fns_; }; template struct any_executor_context { }; #if !defined(ASIO_NO_TS_EXECUTORS) template struct any_executor_context::type> { typename Property::query_result_type context() const { return static_cast(this)->query(typename Property::type()); } }; #endif // !defined(ASIO_NO_TS_EXECUTORS) } // namespace detail template <> class any_executor<> : public detail::any_executor_base { public: any_executor() ASIO_NOEXCEPT : detail::any_executor_base() { } any_executor(nullptr_t) ASIO_NOEXCEPT : detail::any_executor_base() { } template any_executor(Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::value, is_executor, false_type >::type::value >::type* = 0) : detail::any_executor_base( ASIO_MOVE_CAST(Executor)(ex), false_type()) { } #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template any_executor(any_executor other) : detail::any_executor_base( static_cast(other)) { } #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template any_executor(any_executor other) : detail::any_executor_base( static_cast(other)) { } #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) any_executor(const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)) { } any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT { if (this != &other) { detail::any_executor_base::operator=( static_cast(other)); } return *this; } any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT { detail::any_executor_base::operator=(p); return *this; } #if defined(ASIO_HAS_MOVE) any_executor(any_executor&& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast( static_cast(other))) { } any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other) { detail::any_executor_base::operator=( static_cast( static_cast(other))); } return *this; } #endif // defined(ASIO_HAS_MOVE) void swap(any_executor& other) ASIO_NOEXCEPT { detail::any_executor_base::swap( static_cast(other)); } using detail::any_executor_base::execute; using detail::any_executor_base::target; using detail::any_executor_base::target_type; using detail::any_executor_base::operator unspecified_bool_type; using detail::any_executor_base::operator!; bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT { return any_executor_base::equality_helper(other); } }; inline bool operator==(const any_executor<>& a, const any_executor<>& b) ASIO_NOEXCEPT { return a.equality_helper(b); } inline bool operator==(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT { return !a; } inline bool operator==(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT { return !b; } inline bool operator!=(const any_executor<>& a, const any_executor<>& b) ASIO_NOEXCEPT { return !a.equality_helper(b); } inline bool operator!=(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT { return !!a; } inline bool operator!=(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT { return !!b; } inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT { return a.swap(b); } #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template class any_executor : public detail::any_executor_base, public detail::any_executor_context< any_executor, typename detail::supportable_properties< 0, void(SupportableProperties...)>::find_context_as_property> { public: any_executor() ASIO_NOEXCEPT : detail::any_executor_base(), prop_fns_(prop_fns_table()) { } any_executor(nullptr_t) ASIO_NOEXCEPT : detail::any_executor_base(), prop_fns_(prop_fns_table()) { } template any_executor(Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::value, detail::is_valid_target_executor< Executor, void(SupportableProperties...)>, false_type >::type::value >::type* = 0) : detail::any_executor_base( ASIO_MOVE_CAST(Executor)(ex), false_type()), prop_fns_(prop_fns_table()) { } template any_executor(any_executor other, typename enable_if< conditional< !is_same< any_executor, any_executor >::value, typename detail::supportable_properties< 0, void(SupportableProperties...)>::template is_valid_target< any_executor >, false_type >::type::value >::type* = 0) : detail::any_executor_base(ASIO_MOVE_CAST( any_executor)(other), true_type()), prop_fns_(prop_fns_table >()) { } any_executor(const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)), prop_fns_(other.prop_fns_) { } any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT { if (this != &other) { prop_fns_ = other.prop_fns_; detail::any_executor_base::operator=( static_cast(other)); } return *this; } any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT { prop_fns_ = prop_fns_table(); detail::any_executor_base::operator=(p); return *this; } #if defined(ASIO_HAS_MOVE) any_executor(any_executor&& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast( static_cast(other))), prop_fns_(other.prop_fns_) { other.prop_fns_ = prop_fns_table(); } any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other) { prop_fns_ = other.prop_fns_; detail::any_executor_base::operator=( static_cast( static_cast(other))); } return *this; } #endif // defined(ASIO_HAS_MOVE) void swap(any_executor& other) ASIO_NOEXCEPT { if (this != &other) { detail::any_executor_base::swap( static_cast(other)); const prop_fns* tmp_prop_fns = other.prop_fns_; other.prop_fns_ = prop_fns_; prop_fns_ = tmp_prop_fns; } } using detail::any_executor_base::execute; using detail::any_executor_base::target; using detail::any_executor_base::target_type; using detail::any_executor_base::operator unspecified_bool_type; using detail::any_executor_base::operator!; bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT { return any_executor_base::equality_helper(other); } template struct find_convertible_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property {}; template void query(const Property& p, typename enable_if< is_same< typename find_convertible_property::query_result_type, void >::value >::type* = 0) const { typedef find_convertible_property found; prop_fns_[found::index].query(0, object_fns_->target(*this), &static_cast(p)); } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && is_reference< typename find_convertible_property::query_result_type >::value >::type* = 0) const { typedef find_convertible_property found; typename remove_reference< typename found::query_result_type>::type* result = 0; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast(p)); return *result; } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && is_scalar< typename find_convertible_property::query_result_type >::value >::type* = 0) const { typedef find_convertible_property found; typename found::query_result_type result; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast(p)); return result; } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && !is_reference< typename find_convertible_property::query_result_type >::value && !is_scalar< typename find_convertible_property::query_result_type >::value >::type* = 0) const { typedef find_convertible_property found; typename found::query_result_type* result; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast(p)); return *asio::detail::scoped_ptr< typename found::query_result_type>(result); } template struct find_convertible_requirable_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_requirable_property {}; template any_executor require(const Property& p, typename enable_if< find_convertible_requirable_property::value >::type* = 0) const { typedef find_convertible_requirable_property found; return prop_fns_[found::index].require(object_fns_->target(*this), &static_cast(p)); } template struct find_convertible_preferable_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_preferable_property {}; template any_executor prefer(const Property& p, typename enable_if< find_convertible_preferable_property::value >::type* = 0) const { typedef find_convertible_preferable_property found; return prop_fns_[found::index].prefer(object_fns_->target(*this), &static_cast(p)); } //private: template static const prop_fns* prop_fns_table() { static const prop_fns fns[] = { { &detail::any_executor_base::query_fn< Ex, SupportableProperties>, &detail::any_executor_base::require_fn< any_executor, Ex, SupportableProperties>, &detail::any_executor_base::prefer_fn< any_executor, Ex, SupportableProperties> }... }; return fns; } const prop_fns* prop_fns_; }; template inline bool operator==(const any_executor& a, const any_executor& b) ASIO_NOEXCEPT { return a.equality_helper(b); } template inline bool operator==(const any_executor& a, nullptr_t) ASIO_NOEXCEPT { return !a; } template inline bool operator==(nullptr_t, const any_executor& b) ASIO_NOEXCEPT { return !b; } template inline bool operator!=(const any_executor& a, const any_executor& b) ASIO_NOEXCEPT { return !a.equality_helper(b); } template inline bool operator!=(const any_executor& a, nullptr_t) ASIO_NOEXCEPT { return !!a; } template inline bool operator!=(nullptr_t, const any_executor& b) ASIO_NOEXCEPT { return !!b; } template inline void swap(any_executor& a, any_executor& b) ASIO_NOEXCEPT { return a.swap(b); } #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #if defined(ASIO_HAS_MOVE) # define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ any_executor(any_executor&& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast( \ static_cast(other))), \ prop_fns_(other.prop_fns_) \ { \ other.prop_fns_ = prop_fns_table(); \ } \ \ any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \ { \ if (this != &other) \ { \ prop_fns_ = other.prop_fns_; \ detail::any_executor_base::operator=( \ static_cast( \ static_cast(other))); \ } \ return *this; \ } \ /**/ #else // defined(ASIO_HAS_MOVE) # define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS #endif // defined(ASIO_HAS_MOVE) #define ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \ template \ class any_executor : \ public detail::any_executor_base, \ public detail::any_executor_context< \ any_executor, \ typename detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \ { \ public: \ any_executor() ASIO_NOEXCEPT \ : detail::any_executor_base(), \ prop_fns_(prop_fns_table()) \ { \ } \ \ any_executor(nullptr_t) ASIO_NOEXCEPT \ : detail::any_executor_base(), \ prop_fns_(prop_fns_table()) \ { \ } \ \ template \ any_executor(Executor ex, \ typename enable_if< \ conditional< \ !is_same::value \ && !is_base_of::value, \ detail::is_valid_target_executor< \ Executor, void(ASIO_VARIADIC_TARGS(n))>, \ false_type \ >::type::value \ >::type* = 0) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ Executor)(ex), false_type()), \ prop_fns_(prop_fns_table()) \ { \ } \ \ any_executor(const any_executor& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast(other)), \ prop_fns_(other.prop_fns_) \ { \ } \ \ any_executor(any_executor<> other) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ any_executor<>)(other), true_type()), \ prop_fns_(prop_fns_table >()) \ { \ } \ \ template \ any_executor(OtherAnyExecutor other, \ typename enable_if< \ conditional< \ !is_same::value \ && is_base_of::value, \ typename detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ is_valid_target, \ false_type \ >::type::value \ >::type* = 0) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ OtherAnyExecutor)(other), true_type()), \ prop_fns_(prop_fns_table()) \ { \ } \ \ any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \ { \ if (this != &other) \ { \ prop_fns_ = other.prop_fns_; \ detail::any_executor_base::operator=( \ static_cast(other)); \ } \ return *this; \ } \ \ any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT \ { \ prop_fns_ = prop_fns_table(); \ detail::any_executor_base::operator=(p); \ return *this; \ } \ \ ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ \ void swap(any_executor& other) ASIO_NOEXCEPT \ { \ if (this != &other) \ { \ detail::any_executor_base::swap( \ static_cast(other)); \ const prop_fns* tmp_prop_fns = other.prop_fns_; \ other.prop_fns_ = prop_fns_; \ prop_fns_ = tmp_prop_fns; \ } \ } \ \ using detail::any_executor_base::execute; \ using detail::any_executor_base::target; \ using detail::any_executor_base::target_type; \ using detail::any_executor_base::operator unspecified_bool_type; \ using detail::any_executor_base::operator!; \ \ bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT \ { \ return any_executor_base::equality_helper(other); \ } \ \ template \ struct find_convertible_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_property {}; \ \ template \ void query(const Property& p, \ typename enable_if< \ is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ >::type* = 0) const \ { \ typedef find_convertible_property found; \ prop_fns_[found::index].query(0, object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ is_reference< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ typedef find_convertible_property found; \ typename remove_reference< \ typename found::query_result_type>::type* result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return *result; \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ is_scalar< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ typedef find_convertible_property found; \ typename found::query_result_type result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return result; \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ !is_reference< \ typename find_convertible_property::query_result_type \ >::value \ && \ !is_scalar< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ typedef find_convertible_property found; \ typename found::query_result_type* result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return *asio::detail::scoped_ptr< \ typename found::query_result_type>(result); \ } \ \ template \ struct find_convertible_requirable_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_requirable_property {}; \ \ template \ any_executor require(const Property& p, \ typename enable_if< \ find_convertible_requirable_property::value \ >::type* = 0) const \ { \ typedef find_convertible_requirable_property found; \ return prop_fns_[found::index].require(object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ struct find_convertible_preferable_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_preferable_property {}; \ \ template \ any_executor prefer(const Property& p, \ typename enable_if< \ find_convertible_preferable_property::value \ >::type* = 0) const \ { \ typedef find_convertible_preferable_property found; \ return prop_fns_[found::index].prefer(object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ static const prop_fns* prop_fns_table() \ { \ static const prop_fns fns[] = \ { \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ }; \ return fns; \ } \ \ const prop_fns* prop_fns_; \ typedef detail::supportable_properties<0, \ void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ }; \ \ template \ inline bool operator==(const any_executor& a, \ const any_executor& b) ASIO_NOEXCEPT \ { \ return a.equality_helper(b); \ } \ \ template \ inline bool operator==(const any_executor& a, \ nullptr_t) ASIO_NOEXCEPT \ { \ return !a; \ } \ \ template \ inline bool operator==(nullptr_t, \ const any_executor& b) ASIO_NOEXCEPT \ { \ return !b; \ } \ \ template \ inline bool operator!=(const any_executor& a, \ const any_executor& b) ASIO_NOEXCEPT \ { \ return !a.equality_helper(b); \ } \ \ template \ inline bool operator!=(const any_executor& a, \ nullptr_t) ASIO_NOEXCEPT \ { \ return !!a; \ } \ \ template \ inline bool operator!=(nullptr_t, \ const any_executor& b) ASIO_NOEXCEPT \ { \ return !!b; \ } \ \ template \ inline void swap(any_executor& a, \ any_executor& b) ASIO_NOEXCEPT \ { \ return a.swap(b); \ } \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_DEF #undef ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 #undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 #endif // if defined(ASIO_HAS_VARIADIC_TEMPLATES) } // namespace execution namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct equality_comparable > { static const bool is_valid = true; static const bool is_noexcept = true; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <> struct equality_comparable > { static const bool is_valid = true; static const bool is_noexcept = true; }; #define ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \ template \ struct equality_comparable< \ execution::any_executor > \ { \ static const bool is_valid = true; \ static const bool is_noexcept = true; \ }; \ /**/ ASIO_VARIADIC_GENERATE( ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct execute_member, F> { static const bool is_valid = true; static const bool is_noexcept = false; typedef void result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct execute_member, F> { static const bool is_valid = true; static const bool is_noexcept = false; typedef void result_type; }; #define ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \ template \ struct execute_member< \ execution::any_executor, F> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef void result_type; \ }; \ /**/ ASIO_VARIADIC_GENERATE( ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct query_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property::value >::type> { static const bool is_valid = true; static const bool is_noexcept = false; typedef typename execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property::query_result_type result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \ template \ struct query_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_property::value \ >::type> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef typename execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_property::query_result_type result_type; \ }; \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct require_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_requirable_property::value >::type> { static const bool is_valid = true; static const bool is_noexcept = false; typedef execution::any_executor result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \ template \ struct require_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_requirable_property::value \ >::type> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef execution::any_executor result_type; \ }; \ /**/ ASIO_VARIADIC_GENERATE( ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct prefer_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_preferable_property::value >::type> { static const bool is_valid = true; static const bool is_noexcept = false; typedef execution::any_executor result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \ template \ struct prefer_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_preferable_property::value \ >::type> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef execution::any_executor result_type; \ }; \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF) #undef ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) } // namespace traits #endif // defined(GENERATING_DOCUMENTATION) } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_EXECUTION_ANY_EXECUTOR_HPP