diff options
Diffstat (limited to '3rdparty/asio/include/asio/execution/any_executor.hpp')
-rw-r--r-- | 3rdparty/asio/include/asio/execution/any_executor.hpp | 1933 |
1 files changed, 1933 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/execution/any_executor.hpp b/3rdparty/asio/include/asio/execution/any_executor.hpp new file mode 100644 index 00000000000..a057543b139 --- /dev/null +++ b/3rdparty/asio/include/asio/execution/any_executor.hpp @@ -0,0 +1,1933 @@ +// +// execution/any_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 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 <new> +#include <typeinfo> +#include "asio/detail/assert.hpp" +#include "asio/detail/atomic_count.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/execution/bad_executor.hpp" +#include "asio/execution/blocking.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 <typename... SupportableProperties> +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 <class... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> e); + + /// Construct to point to the same target as another any_executor. + template <class... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> e) noexcept; + + /// Construct to point to the same target as another any_executor. + any_executor(std::nothrow_t, const any_executor& e) noexcept; + + /// Construct to point to the same target as another any_executor. + any_executor(std::nothrow_t, any_executor&& e) noexcept; + + /// Construct a polymorphic wrapper for the specified executor. + template <typename Executor> + any_executor(Executor e); + + /// Construct a polymorphic wrapper for the specified executor. + template <typename Executor> + any_executor(std::nothrow_t, Executor e) noexcept; + + /// 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 <typename Executor> + 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<execution::blocking_t::possibly_t> ex = ...; + * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode + */ + template <typename Property> + 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<execution::blocking_t::possibly_t> ex = ...; + * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode + */ + template <typename Property> + 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<execution::occupancy_t> ex = ...; + * size_t n = asio::query(ex, execution::occupancy); @endcode + */ + template <typename Property> + typename Property::polymorphic_query_result_type query(Property) const; + + /// Execute the function on the target executor. + /** + * Throws asio::bad_executor if the polymorphic wrapper has no target. + */ + template <typename Function> + 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 <tt>execution::context_as<U></tt>, for some type <tt>U</tt>. + */ + 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 <typename Executor> Executor* target() noexcept; + + /// Get a pointer to the target executor. + template <typename Executor> const Executor* target() const noexcept; +}; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(const any_executor<SupportableProperties...>& a, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(const any_executor<SupportableProperties...>& a, + nullptr_t) noexcept; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(nullptr_t, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(const any_executor<SupportableProperties...>& a, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(const any_executor<SupportableProperties...>& a, + nullptr_t) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(nullptr_t, + const any_executor<SupportableProperties...>& 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 + +template <typename... SupportableProperties> +class any_executor; + +#endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) + +template <typename U> +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 <typename T, typename = void> +struct is_requirable : false_type {}; + +template <typename T> +struct is_requirable<T, enable_if_t<T::is_requirable>> : true_type {}; + +template <typename T, typename = void> +struct is_preferable : false_type {}; + +template <typename T> +struct is_preferable<T, enable_if_t<T::is_preferable>> : true_type {}; + +// Trait used to detect context_as property, for backward compatibility. + +template <typename T> +struct is_context_as : false_type {}; + +template <typename U> +struct is_context_as<context_as_t<U>> : 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 <std::size_t I, typename Props> +struct supportable_properties; + +template <std::size_t I, typename Prop> +struct supportable_properties<I, void(Prop)> +{ + template <typename T> + struct is_valid_target : integral_constant<bool, + ( + is_requirable<Prop>::value + ? can_require<T, Prop>::value + : true + ) + && + ( + is_preferable<Prop>::value + ? can_prefer<T, Prop>::value + : true + ) + && + ( + !is_requirable<Prop>::value && !is_preferable<Prop>::value + ? can_query<T, Prop>::value + : true + ) + > + { + }; + + struct found + { + static constexpr bool value = true; + typedef Prop type; + typedef typename Prop::polymorphic_query_result_type query_result_type; + static constexpr std::size_t index = I; + }; + + struct not_found + { + static constexpr bool value = false; + }; + + template <typename T> + struct find_convertible_property : + conditional_t< + is_same<T, Prop>::value || is_convertible<T, Prop>::value, + found, + not_found + > {}; + + template <typename T> + struct find_convertible_requirable_property : + conditional_t< + is_requirable<Prop>::value + && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), + found, + not_found + > {}; + + template <typename T> + struct find_convertible_preferable_property : + conditional_t< + is_preferable<Prop>::value + && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), + found, + not_found + > {}; + + struct find_context_as_property : + conditional_t< + is_context_as<Prop>::value, + found, + not_found + > {}; +}; + +template <std::size_t I, typename Head, typename... Tail> +struct supportable_properties<I, void(Head, Tail...)> +{ + template <typename T> + struct is_valid_target : integral_constant<bool, + ( + supportable_properties<I, + void(Head)>::template is_valid_target<T>::value + && + supportable_properties<I + 1, + void(Tail...)>::template is_valid_target<T>::value + ) + > + { + }; + + template <typename T> + struct find_convertible_property : + conditional_t< + is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_property<T> + > {}; + + template <typename T> + struct find_convertible_requirable_property : + conditional_t< + is_requirable<Head>::value + && is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_requirable_property<T> + > {}; + + template <typename T> + struct find_convertible_preferable_property : + conditional_t< + is_preferable<Head>::value + && is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_preferable_property<T> + > {}; + + struct find_context_as_property : + conditional_t< + is_context_as<Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::find_context_as_property + > {}; +}; + +template <typename T, typename Props> +struct is_valid_target_executor : + conditional_t< + is_executor<T>::value, + typename supportable_properties<0, Props>::template is_valid_target<T>, + false_type + > +{ +}; + +template <typename Props> +struct is_valid_target_executor<int, Props> : false_type +{ +}; + +class shared_target_executor +{ +public: + template <typename E> + shared_target_executor(E&& e, decay_t<E>*& target) + { + impl<decay_t<E>>* i = + new impl<decay_t<E>>(static_cast<E&&>(e)); + target = &i->ex_; + impl_ = i; + } + + template <typename E> + shared_target_executor(std::nothrow_t, E&& e, decay_t<E>*& target) noexcept + { + impl<decay_t<E>>* i = + new (std::nothrow) impl<decay_t<E>>(static_cast<E&&>(e)); + target = i ? &i->ex_ : 0; + impl_ = i; + } + + shared_target_executor(const shared_target_executor& other) noexcept + : impl_(other.impl_) + { + if (impl_) + asio::detail::ref_count_up(impl_->ref_count_); + } + + shared_target_executor(shared_target_executor&& other) noexcept + : impl_(other.impl_) + { + other.impl_ = 0; + } + + ~shared_target_executor() + { + if (impl_) + if (asio::detail::ref_count_down(impl_->ref_count_)) + delete impl_; + } + + void* get() const noexcept + { + return impl_ ? impl_->get() : 0; + } + +private: + shared_target_executor& operator=( + const shared_target_executor& other) = delete; + + shared_target_executor& operator=( + shared_target_executor&& other) = delete; + + struct impl_base + { + impl_base() : ref_count_(1) {} + virtual ~impl_base() {} + virtual void* get() = 0; + asio::detail::atomic_count ref_count_; + }; + + template <typename Executor> + struct impl : impl_base + { + impl(Executor ex) : ex_(static_cast<Executor&&>(ex)) {} + virtual void* get() { return &ex_; } + Executor ex_; + }; + + impl_base* impl_; +}; + +class any_executor_base +{ +public: + any_executor_base() noexcept + : object_fns_(0), + target_(0), + target_fns_(0) + { + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(Executor ex, false_type) + : target_fns_(target_fns_table<Executor>( + any_executor_base::query_blocking(ex, + can_query<const Executor&, const execution::blocking_t&>()) + == execution::blocking.always)) + { + any_executor_base::construct_object(ex, + integral_constant<bool, + sizeof(Executor) <= sizeof(object_type) + && alignment_of<Executor>::value <= alignment_of<object_type>::value + >()); + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(std::nothrow_t, Executor ex, false_type) noexcept + : target_fns_(target_fns_table<Executor>( + any_executor_base::query_blocking(ex, + can_query<const Executor&, const execution::blocking_t&>()) + == execution::blocking.always)) + { + any_executor_base::construct_object(std::nothrow, ex, + integral_constant<bool, + sizeof(Executor) <= sizeof(object_type) + && alignment_of<Executor>::value <= alignment_of<object_type>::value + >()); + if (target_ == 0) + { + object_fns_ = 0; + target_fns_ = 0; + } + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(Executor other, true_type) + : object_fns_(object_fns_table<shared_target_executor>()), + target_fns_(other.target_fns_) + { + Executor* p = 0; + new (&object_) shared_target_executor( + static_cast<Executor&&>(other), p); + target_ = p->template target<void>(); + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(std::nothrow_t, + Executor other, true_type) noexcept + : object_fns_(object_fns_table<shared_target_executor>()), + target_fns_(other.target_fns_) + { + Executor* p = 0; + new (&object_) shared_target_executor( + std::nothrow, static_cast<Executor&&>(other), p); + if (p) + target_ = p->template target<void>(); + else + { + target_ = 0; + object_fns_ = 0; + target_fns_ = 0; + } + } + + any_executor_base(const any_executor_base& other) noexcept + { + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + object_fns_->copy(*this, other); + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } + } + + ~any_executor_base() noexcept + { + if (!!*this) + object_fns_->destroy(*this); + } + + any_executor_base& operator=( + const any_executor_base& other) noexcept + { + if (this != &other) + { + if (!!*this) + object_fns_->destroy(*this); + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + object_fns_->copy(*this, other); + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } + } + return *this; + } + + any_executor_base& operator=(nullptr_t) noexcept + { + if (target_) + object_fns_->destroy(*this); + target_ = 0; + object_fns_ = 0; + target_fns_ = 0; + return *this; + } + + any_executor_base(any_executor_base&& other) noexcept + { + if (other.target_) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + other.object_fns_ = 0; + other.target_fns_ = 0; + object_fns_->move(*this, other); + other.target_ = 0; + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } + } + + any_executor_base& operator=( + any_executor_base&& other) noexcept + { + if (this != &other) + { + if (!!*this) + object_fns_->destroy(*this); + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + other.object_fns_ = 0; + other.target_fns_ = 0; + object_fns_->move(*this, other); + other.target_ = 0; + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } + } + return *this; + } + + void swap(any_executor_base& other) noexcept + { + if (this != &other) + { + any_executor_base tmp(static_cast<any_executor_base&&>(other)); + other = static_cast<any_executor_base&&>(*this); + *this = static_cast<any_executor_base&&>(tmp); + } + } + + template <typename F> + void execute(F&& f) const + { + if (target_) + { + if (target_fns_->blocking_execute != 0) + { + asio::detail::non_const_lvalue<F> f2(f); + target_fns_->blocking_execute(*this, function_view(f2.value)); + } + else + { + target_fns_->execute(*this, + function(static_cast<F&&>(f), std::allocator<void>())); + } + } + else + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + } + + template <typename Executor> + Executor* target() + { + return target_ && (is_same<Executor, void>::value + || target_fns_->target_type() == target_type_ex<Executor>()) + ? static_cast<Executor*>(target_) : 0; + } + + template <typename Executor> + const Executor* target() const + { + return target_ && (is_same<Executor, void>::value + || target_fns_->target_type() == target_type_ex<Executor>()) + ? static_cast<const Executor*>(target_) : 0; + } + +#if !defined(ASIO_NO_TYPEID) + const std::type_info& target_type() const + { + return target_ ? target_fns_->target_type() : typeid(void); + } +#else // !defined(ASIO_NO_TYPEID) + const void* target_type() const + { + return target_ ? target_fns_->target_type() : 0; + } +#endif // !defined(ASIO_NO_TYPEID) + + 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 noexcept + { + return target_ ? &any_executor_base::unspecified_bool_true : 0; + } + + bool operator!() const noexcept + { + return target_ == 0; + } + +protected: + bool equality_helper(const any_executor_base& other) const 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 <typename Ex> + Ex& object() + { + return *static_cast<Ex*>(static_cast<void*>(&object_)); + } + + template <typename Ex> + const Ex& object() const + { + return *static_cast<const Ex*>(static_cast<const void*>(&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_shared(any_executor_base& ex) + { + typedef shared_target_executor type; + ex.object<type>().~type(); + } + + static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) + { + typedef shared_target_executor type; + new (&ex1.object_) type(ex2.object<type>()); + ex1.target_ = ex2.target_; + } + + static void move_shared(any_executor_base& ex1, any_executor_base& ex2) + { + typedef shared_target_executor type; + new (&ex1.object_) type(static_cast<type&&>(ex2.object<type>())); + ex1.target_ = ex2.target_; + ex2.object<type>().~type(); + } + + static const void* target_shared(const any_executor_base& ex) + { + typedef shared_target_executor type; + return ex.object<type>().get(); + } + + template <typename Obj> + static const object_fns* object_fns_table( + enable_if_t< + is_same<Obj, shared_target_executor>::value + >* = 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 <typename Obj> + static void destroy_object(any_executor_base& ex) + { + ex.object<Obj>().~Obj(); + } + + template <typename Obj> + static void copy_object(any_executor_base& ex1, const any_executor_base& ex2) + { + new (&ex1.object_) Obj(ex2.object<Obj>()); + ex1.target_ = &ex1.object<Obj>(); + } + + template <typename Obj> + static void move_object(any_executor_base& ex1, any_executor_base& ex2) + { + new (&ex1.object_) Obj(static_cast<Obj&&>(ex2.object<Obj>())); + ex1.target_ = &ex1.object<Obj>(); + ex2.object<Obj>().~Obj(); + } + + template <typename Obj> + static const void* target_object(const any_executor_base& ex) + { + return &ex.object<Obj>(); + } + + template <typename Obj> + static const object_fns* object_fns_table( + enable_if_t< + !is_same<Obj, void>::value + && !is_same<Obj, shared_target_executor>::value + >* = 0) + { + static const object_fns fns = + { + &any_executor_base::destroy_object<Obj>, + &any_executor_base::copy_object<Obj>, + &any_executor_base::move_object<Obj>, + &any_executor_base::target_object<Obj> + }; + return &fns; + } + + typedef asio::detail::executor_function function; + typedef asio::detail::executor_function_view function_view; + + struct target_fns + { +#if !defined(ASIO_NO_TYPEID) + const std::type_info& (*target_type)(); +#else // !defined(ASIO_NO_TYPEID) + const void* (*target_type)(); +#endif // !defined(ASIO_NO_TYPEID) + bool (*equal)(const any_executor_base&, const any_executor_base&); + void (*execute)(const any_executor_base&, function&&); + void (*blocking_execute)(const any_executor_base&, function_view); + }; + +#if !defined(ASIO_NO_TYPEID) + template <typename Ex> + static const std::type_info& target_type_ex() + { + return typeid(Ex); + } +#else // !defined(ASIO_NO_TYPEID) + template <typename Ex> + static const void* target_type_ex() + { + static int unique_id; + return &unique_id; + } +#endif // !defined(ASIO_NO_TYPEID) + + template <typename Ex> + static bool equal_ex(const any_executor_base& ex1, + const any_executor_base& ex2) + { + const Ex* p1 = ex1.target<Ex>(); + const Ex* p2 = ex2.target<Ex>(); + ASIO_ASSUME(p1 != 0 && p2 != 0); + return *p1 == *p2; + } + + template <typename Ex> + static void execute_ex(const any_executor_base& ex, function&& f) + { + const Ex* p = ex.target<Ex>(); + ASIO_ASSUME(p != 0); + p->execute(static_cast<function&&>(f)); + } + + template <typename Ex> + static void blocking_execute_ex(const any_executor_base& ex, function_view f) + { + const Ex* p = ex.target<Ex>(); + ASIO_ASSUME(p != 0); + p->execute(f); + } + + template <typename Ex> + static const target_fns* target_fns_table(bool is_always_blocking, + enable_if_t< + !is_same<Ex, void>::value + >* = 0) + { + static const target_fns fns_with_execute = + { + &any_executor_base::target_type_ex<Ex>, + &any_executor_base::equal_ex<Ex>, + &any_executor_base::execute_ex<Ex>, + 0 + }; + + static const target_fns fns_with_blocking_execute = + { + &any_executor_base::target_type_ex<Ex>, + &any_executor_base::equal_ex<Ex>, + 0, + &any_executor_base::blocking_execute_ex<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 <typename Ex, class Prop> + static void query_fn_non_void(void*, const void* ex, const void* prop, + enable_if_t< + asio::can_query<const Ex&, const Prop&>::value + && is_same<typename Prop::polymorphic_query_result_type, void>::value + >*) + { + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void*, const void*, const void*, + enable_if_t< + !asio::can_query<const Ex&, const Prop&>::value + && is_same<typename Prop::polymorphic_query_result_type, void>::value + >*) + { + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + enable_if_t< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_reference<typename Prop::polymorphic_query_result_type>::value + >*) + { + *static_cast<remove_reference_t< + typename Prop::polymorphic_query_result_type>**>(result) + = &static_cast<typename Prop::polymorphic_query_result_type>( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void*, const void*, const void*, + enable_if_t< + !asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_reference<typename Prop::polymorphic_query_result_type>::value + >*) + { + std::terminate(); // Combination should not be possible. + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + enable_if_t< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_scalar<typename Prop::polymorphic_query_result_type>::value + >*) + { + *static_cast<typename Prop::polymorphic_query_result_type*>(result) + = static_cast<typename Prop::polymorphic_query_result_type>( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void*, const void*, + enable_if_t< + !asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_scalar<typename Prop::polymorphic_query_result_type>::value + >*) + { + *static_cast<typename Prop::polymorphic_query_result_type*>(result) + = typename Prop::polymorphic_query_result_type(); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + enable_if_t< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && !is_reference<typename Prop::polymorphic_query_result_type>::value + && !is_scalar<typename Prop::polymorphic_query_result_type>::value + >*) + { + *static_cast<typename Prop::polymorphic_query_result_type**>(result) + = new typename Prop::polymorphic_query_result_type( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void*, const void*, ...) + { + *static_cast<typename Prop::polymorphic_query_result_type**>(result) + = new typename Prop::polymorphic_query_result_type(); + } + + template <typename Ex, class Prop> + static void query_fn_impl(void* result, const void* ex, const void* prop, + enable_if_t< + is_same<Ex, void>::value + >*) + { + query_fn_void(result, ex, prop); + } + + template <typename Ex, class Prop> + static void query_fn_impl(void* result, const void* ex, const void* prop, + enable_if_t< + !is_same<Ex, void>::value + >*) + { + query_fn_non_void<Ex, Prop>(result, ex, prop, 0); + } + + template <typename Ex, class Prop> + static void query_fn(void* result, const void* ex, const void* prop) + { + query_fn_impl<Ex, Prop>(result, ex, prop, 0); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void*, const void*, + enable_if_t< + is_same<Ex, void>::value + >*) + { + bad_executor ex; + asio::detail::throw_exception(ex); + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void* ex, const void* prop, + enable_if_t< + !is_same<Ex, void>::value && Prop::is_requirable + >*) + { + return asio::require(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void*, const void*, ...) + { + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn(const void* ex, const void* prop) + { + return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void*, const void*, + enable_if_t< + is_same<Ex, void>::value + >*) + { + bad_executor ex; + asio::detail::throw_exception(ex); + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void* ex, const void* prop, + enable_if_t< + !is_same<Ex, void>::value && Prop::is_preferable + >*) + { + return asio::prefer(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void*, const void*, ...) + { + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn(const void* ex, const void* prop) + { + return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0); + } + + template <typename Poly> + 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 <typename Executor> + static execution::blocking_t query_blocking(const Executor& ex, true_type) + { + return asio::query(ex, execution::blocking); + } + + template <typename Executor> + static execution::blocking_t query_blocking(const Executor&, false_type) + { + return execution::blocking_t(); + } + + template <typename Executor> + void construct_object(Executor& ex, true_type) + { + object_fns_ = object_fns_table<Executor>(); + target_ = new (&object_) Executor(static_cast<Executor&&>(ex)); + } + + template <typename Executor> + void construct_object(Executor& ex, false_type) + { + object_fns_ = object_fns_table<shared_target_executor>(); + Executor* p = 0; + new (&object_) shared_target_executor( + static_cast<Executor&&>(ex), p); + target_ = p; + } + + template <typename Executor> + void construct_object(std::nothrow_t, + Executor& ex, true_type) noexcept + { + object_fns_ = object_fns_table<Executor>(); + target_ = new (&object_) Executor(static_cast<Executor&&>(ex)); + } + + template <typename Executor> + void construct_object(std::nothrow_t, + Executor& ex, false_type) noexcept + { + object_fns_ = object_fns_table<shared_target_executor>(); + Executor* p = 0; + new (&object_) shared_target_executor( + std::nothrow, static_cast<Executor&&>(ex), p); + target_ = p; + } + +/*private:*/public: +// template <typename...> friend class any_executor; + + typedef aligned_storage< + sizeof(asio::detail::shared_ptr<void>) + sizeof(void*), + alignment_of<asio::detail::shared_ptr<void>>::value + >::type object_type; + + object_type object_; + const object_fns* object_fns_; + void* target_; + const target_fns* target_fns_; +}; + +template <typename Derived, typename Property, typename = void> +struct any_executor_context +{ +}; + +#if !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Derived, typename Property> +struct any_executor_context<Derived, Property, enable_if_t<Property::value>> +{ + typename Property::query_result_type context() const + { + return static_cast<const Derived*>(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() noexcept + : detail::any_executor_base() + { + } + + any_executor(nullptr_t) noexcept + : detail::any_executor_base() + { + } + + template <typename Executor> + any_executor(Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + is_executor<Executor>, + false_type + >::value + >* = 0) + : detail::any_executor_base( + static_cast<Executor&&>(ex), false_type()) + { + } + + template <typename Executor> + any_executor(std::nothrow_t, Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + is_executor<Executor>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<Executor&&>(ex), false_type()) + { + } + + template <typename... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> other) + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + + template <typename... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + + any_executor(const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + + any_executor(std::nothrow_t, const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + + any_executor& operator=(const any_executor& other) noexcept + { + if (this != &other) + { + detail::any_executor_base::operator=( + static_cast<const detail::any_executor_base&>(other)); + } + return *this; + } + + any_executor& operator=(nullptr_t p) noexcept + { + detail::any_executor_base::operator=(p); + return *this; + } + + any_executor(any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))) + { + } + + any_executor(std::nothrow_t, any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))) + { + } + + any_executor& operator=(any_executor&& other) noexcept + { + if (this != &other) + { + detail::any_executor_base::operator=( + static_cast<detail::any_executor_base&&>( + static_cast<detail::any_executor_base&>(other))); + } + return *this; + } + + void swap(any_executor& other) noexcept + { + detail::any_executor_base::swap( + static_cast<detail::any_executor_base&>(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 noexcept + { + return any_executor_base::equality_helper(other); + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend enable_if_t< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + > operator==(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept + { + return static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator==(const AnyExecutor& a, nullptr_t) noexcept + { + return !a; + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator==(nullptr_t, const AnyExecutor& b) noexcept + { + return !b; + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend enable_if_t< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + > operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept + { + return !static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator!=(const AnyExecutor& a, nullptr_t) noexcept + { + return !!a; + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator!=(nullptr_t, const AnyExecutor& b) noexcept + { + return !!b; + } +}; + +inline void swap(any_executor<>& a, any_executor<>& b) noexcept +{ + return a.swap(b); +} + +template <typename... SupportableProperties> +class any_executor : + public detail::any_executor_base, + public detail::any_executor_context< + any_executor<SupportableProperties...>, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::find_context_as_property> +{ +public: + any_executor() noexcept + : detail::any_executor_base(), + prop_fns_(prop_fns_table<void>()) + { + } + + any_executor(nullptr_t) noexcept + : detail::any_executor_base(), + prop_fns_(prop_fns_table<void>()) + { + } + + template <typename Executor> + any_executor(Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + detail::is_valid_target_executor< + Executor, void(SupportableProperties...)>, + false_type + >::value + >* = 0) + : detail::any_executor_base( + static_cast<Executor&&>(ex), false_type()), + prop_fns_(prop_fns_table<Executor>()) + { + } + + template <typename Executor> + any_executor(std::nothrow_t, Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + detail::is_valid_target_executor< + Executor, void(SupportableProperties...)>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<Executor&&>(ex), false_type()), + prop_fns_(prop_fns_table<Executor>()) + { + if (this->template target<void>() == 0) + prop_fns_ = prop_fns_table<void>(); + } + + template <typename... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> other, + enable_if_t< + conditional_t< + !is_same< + any_executor<OtherSupportableProperties...>, + any_executor + >::value, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::template is_valid_target< + any_executor<OtherSupportableProperties...>>, + false_type + >::value + >* = 0) + : detail::any_executor_base( + static_cast<any_executor<OtherSupportableProperties...>&&>(other), + true_type()), + prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>()) + { + } + + template <typename... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> other, + enable_if_t< + conditional_t< + !is_same< + any_executor<OtherSupportableProperties...>, + any_executor + >::value, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::template is_valid_target< + any_executor<OtherSupportableProperties...>>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<any_executor<OtherSupportableProperties...>&&>(other), + true_type()), + prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>()) + { + if (this->template target<void>() == 0) + prop_fns_ = prop_fns_table<void>(); + } + + any_executor(const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)), + prop_fns_(other.prop_fns_) + { + } + + any_executor(std::nothrow_t, const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)), + prop_fns_(other.prop_fns_) + { + } + + any_executor& operator=(const any_executor& other) noexcept + { + if (this != &other) + { + prop_fns_ = other.prop_fns_; + detail::any_executor_base::operator=( + static_cast<const detail::any_executor_base&>(other)); + } + return *this; + } + + any_executor& operator=(nullptr_t p) noexcept + { + prop_fns_ = prop_fns_table<void>(); + detail::any_executor_base::operator=(p); + return *this; + } + + any_executor(any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))), + prop_fns_(other.prop_fns_) + { + other.prop_fns_ = prop_fns_table<void>(); + } + + any_executor(std::nothrow_t, any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))), + prop_fns_(other.prop_fns_) + { + other.prop_fns_ = prop_fns_table<void>(); + } + + any_executor& operator=(any_executor&& other) noexcept + { + if (this != &other) + { + prop_fns_ = other.prop_fns_; + detail::any_executor_base::operator=( + static_cast<detail::any_executor_base&&>( + static_cast<detail::any_executor_base&>(other))); + } + return *this; + } + + void swap(any_executor& other) noexcept + { + if (this != &other) + { + detail::any_executor_base::swap( + static_cast<detail::any_executor_base&>(other)); + const prop_fns<any_executor>* 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 noexcept + { + return any_executor_base::equality_helper(other); + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend enable_if_t< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + > operator==(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept + { + return static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator==(const AnyExecutor& a, nullptr_t) noexcept + { + return !a; + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator==(nullptr_t, const AnyExecutor& b) noexcept + { + return !b; + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend enable_if_t< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + > operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept + { + return !static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator!=(const AnyExecutor& a, nullptr_t) noexcept + { + return !!a; + } + + template <typename AnyExecutor> + friend enable_if_t< + is_same<AnyExecutor, any_executor>::value, + bool + > operator!=(nullptr_t, const AnyExecutor& b) noexcept + { + return !!b; + } + + template <typename T> + struct find_convertible_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<T> {}; + + template <typename Property> + void query(const Property& p, + enable_if_t< + is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_property<Property> found; + prop_fns_[found::index].query(0, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + enable_if_t< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + is_reference< + typename find_convertible_property<Property>::query_result_type + >::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_property<Property> found; + remove_reference_t<typename found::query_result_type>* result = 0; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return *result; + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + enable_if_t< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + is_scalar< + typename find_convertible_property<Property>::query_result_type + >::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_property<Property> found; + typename found::query_result_type result; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return result; + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + enable_if_t< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + !is_reference< + typename find_convertible_property<Property>::query_result_type + >::value + && + !is_scalar< + typename find_convertible_property<Property>::query_result_type + >::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_property<Property> found; + typename found::query_result_type* result; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return *asio::detail::scoped_ptr< + typename found::query_result_type>(result); + } + + template <typename T> + struct find_convertible_requirable_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_requirable_property<T> {}; + + template <typename Property> + any_executor require(const Property& p, + enable_if_t< + find_convertible_requirable_property<Property>::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_requirable_property<Property> found; + return prop_fns_[found::index].require(object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + + template <typename T> + struct find_convertible_preferable_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_preferable_property<T> {}; + + template <typename Property> + any_executor prefer(const Property& p, + enable_if_t< + find_convertible_preferable_property<Property>::value + >* = 0) const + { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + typedef find_convertible_preferable_property<Property> found; + return prop_fns_[found::index].prefer(object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + +//private: + template <typename Ex> + static const prop_fns<any_executor>* prop_fns_table() + { + static const prop_fns<any_executor> 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<any_executor>* prop_fns_; +}; + +template <typename... SupportableProperties> +inline void swap(any_executor<SupportableProperties...>& a, + any_executor<SupportableProperties...>& b) noexcept +{ + return a.swap(b); +} + +} // namespace execution +namespace traits { + +#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) + +template <typename... SupportableProperties> +struct equality_comparable<execution::any_executor<SupportableProperties...>> +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) + +template <typename F, typename... SupportableProperties> +struct execute_member<execution::any_executor<SupportableProperties...>, F> +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; + typedef void result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +template <typename Prop, typename... SupportableProperties> +struct query_member< + execution::any_executor<SupportableProperties...>, Prop, + enable_if_t< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<Prop>::value + >> +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; + typedef typename execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<Prop>::query_result_type result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) + +template <typename Prop, typename... SupportableProperties> +struct require_member< + execution::any_executor<SupportableProperties...>, Prop, + enable_if_t< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_requirable_property<Prop>::value + >> +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; + typedef execution::any_executor<SupportableProperties...> result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) + +template <typename Prop, typename... SupportableProperties> +struct prefer_member< + execution::any_executor<SupportableProperties...>, Prop, + enable_if_t< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_preferable_property<Prop>::value + >> +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; + typedef execution::any_executor<SupportableProperties...> result_type; +}; + +#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 |