// // disposition.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2025 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_DISPOSITION_HPP #define ASIO_DISPOSITION_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include "asio/detail/throw_exception.hpp" #include "asio/detail/type_traits.hpp" #include "asio/error_code.hpp" #include "asio/system_error.hpp" #include #include "asio/detail/push_options.hpp" namespace asio { /// Traits type to adapt arbitrary error types as dispositions. /** * This type may be specialised for user-defined types, to allow them to be * treated as a disposition by asio. * * The primary trait is not defined. */ #if defined(GENERATING_DOCUMENTATION) template struct disposition_traits { /// Determine whether a disposition represents no error. static bool not_an_error(const T& d) noexcept; /// Throw an exception if the disposition represents an error. static void throw_exception(T d); /// Convert a disposition into an @c exception_ptr. static std::exception_ptr to_exception_ptr(T d) noexcept; }; #else // defined(GENERATING_DOCUMENTATION) template struct disposition_traits; #endif // defined(GENERATING_DOCUMENTATION) namespace detail { template struct is_disposition_impl : false_type { }; template struct is_disposition_impl::value >, enable_if_t< is_nothrow_move_constructible::value >, enable_if_t< is_nothrow_move_assignable::value >, enable_if_t< is_same< decltype(disposition_traits::not_an_error(declval())), bool >::value >, void_t< decltype(disposition_traits::throw_exception(declval())) >, enable_if_t< is_same< decltype(disposition_traits::to_exception_ptr(declval())), std::exception_ptr >::value >> : true_type { }; } // namespace detail /// Trait used for testing whether a type satisfies the requirements of a /// disposition. /** * To be a valid disposition, a type must be nothrow default-constructible, * nothrow move-constructible, nothrow move-assignable, and there must be a * specialisation of the disposition_traits template for the type that provides * the following static member functions: * @li @c not_an_error: Takes an argument of type const T& and returns * a @c bool. * @li @c throw_exception: Takes an argument of type T. The * caller of this function must not pass a disposition value for which * @c not_an_error returns true. This function must not return. * @li @c to_exception_ptr: Takes an argument of type T and returns a * value of type @c std::exception_ptr. */ template struct is_disposition : #if defined(GENERATING_DOCUMENTATION) integral_constant #else // defined(GENERATING_DOCUMENTATION) detail::is_disposition_impl #endif // defined(GENERATING_DOCUMENTATION) { }; #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template constexpr const bool is_disposition_v = is_disposition::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) #if defined(ASIO_HAS_CONCEPTS) template ASIO_CONCEPT disposition = is_disposition::value; #define ASIO_DISPOSITION ::asio::disposition #else // defined(ASIO_HAS_CONCEPTS) #define ASIO_DISPOSITION typename #endif // defined(ASIO_HAS_CONCEPTS) /// Specialisation of @c disposition_traits for @c error_code. template <> struct disposition_traits { static bool not_an_error(const asio::error_code& ec) noexcept { return !ec; } static void throw_exception(const asio::error_code& ec) { detail::throw_exception(asio::system_error(ec)); } static std::exception_ptr to_exception_ptr( const asio::error_code& ec) noexcept { return ec ? std::make_exception_ptr(asio::system_error(ec)) : nullptr; } }; /// Specialisation of @c disposition_traits for @c std::exception_ptr. template <> struct disposition_traits { static bool not_an_error(const std::exception_ptr& e) noexcept { return !e; } static void throw_exception(std::exception_ptr e) { std::rethrow_exception(static_cast(e)); } static std::exception_ptr to_exception_ptr(std::exception_ptr e) noexcept { return e; } }; /// A tag type used to indicate the absence of an error. struct no_error_t { /// Default constructor. constexpr no_error_t() { } /// Equality operator. friend constexpr bool operator==( const no_error_t&, const no_error_t&) noexcept { return true; } /// Inequality operator. friend constexpr bool operator!=( const no_error_t&, const no_error_t&) noexcept { return false; } /// Equality operator, returns true if the disposition does not contain an /// error. template friend constexpr constraint_t::value, bool> operator==(const no_error_t&, const Disposition& d) noexcept { return disposition_traits::not_an_error(d); } /// Equality operator, returns true if the disposition does not contain an /// error. template friend constexpr constraint_t::value, bool> operator==(const Disposition& d, const no_error_t&) noexcept { return disposition_traits::not_an_error(d); } /// Inequality operator, returns true if the disposition contains an error. template friend constexpr constraint_t::value, bool> operator!=(const no_error_t&, const Disposition& d) noexcept { return !disposition_traits::not_an_error(d); } /// Inequality operator, returns true if the disposition contains an error. template friend constexpr constraint_t::value, bool> operator!=(const Disposition& d, const no_error_t&) noexcept { return !disposition_traits::not_an_error(d); } }; /// A special value used to indicate the absence of an error. ASIO_INLINE_VARIABLE constexpr no_error_t no_error; /// Specialisation of @c disposition_traits for @c no_error_t. template <> struct disposition_traits { static bool not_an_error(no_error_t) noexcept { return true; } static void throw_exception(no_error_t) { } static std::exception_ptr to_exception_ptr(no_error_t) noexcept { return std::exception_ptr(); } }; /// Helper function to throw an exception arising from a disposition. template inline void throw_exception(Disposition&& d, constraint_t>::value> = 0) { disposition_traits>::throw_exception( static_cast(d)); } /// Helper function to convert a disposition to an @c exception_ptr. template inline std::exception_ptr to_exception_ptr(Disposition&& d, constraint_t>::value> = 0) noexcept { return disposition_traits>::to_exception_ptr( static_cast(d)); } } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_DISPOSITION_HPP