// // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2018 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 BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP #define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include // Older versions of gcc have difficulty compiling the sizeof expressions where // we test the handler type requirements. We'll disable checking of handler type // requirements for those compilers, but otherwise enable it by default. #if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) # if !defined(__GNUC__) || (__GNUC__ >= 4) # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 # endif // !defined(__GNUC__) || (__GNUC__ >= 4) #endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) // With C++0x we can use a combination of enhanced SFINAE and static_assert to // generate better template error messages. As this technique is not yet widely // portable, we'll only enable it for tested compilers. #if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) # if defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # if defined(__GXX_EXPERIMENTAL_CXX0X__) # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # endif // defined(__GNUC__) # if defined(BOOST_ASIO_MSVC) # if (_MSC_VER >= 1600) # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 # endif // (_MSC_VER >= 1600) # endif // defined(BOOST_ASIO_MSVC) # if defined(__clang__) # if __has_feature(__cxx_static_assert__) # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 # endif // __has_feature(cxx_static_assert) # endif // defined(__clang__) #endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) # include #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) namespace boost { namespace asio { namespace detail { #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) # if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) template auto zero_arg_copyable_handler_test(Handler h, void*) -> decltype( sizeof(Handler(static_cast(h))), ((h)()), char(0)); template char (&zero_arg_copyable_handler_test(Handler, ...))[2]; template auto one_arg_handler_test(Handler h, Arg1* a1) -> decltype( sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ((h)(*a1)), char(0)); template char (&one_arg_handler_test(Handler h, ...))[2]; template auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) -> decltype( sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ((h)(*a1, *a2)), char(0)); template char (&two_arg_handler_test(Handler, ...))[2]; template auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) -> decltype( sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))), ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))), char(0)); template char (&two_arg_move_handler_test(Handler, ...))[2]; # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ static_assert(expr, msg); # else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) # endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) template T& lvref(); template T& lvref(T); template const T& clvref(); template const T& clvref(T); #if defined(BOOST_ASIO_HAS_MOVE) template T rvref(); template T rvref(T); #else // defined(BOOST_ASIO_HAS_MOVE) template const T& rvref(); template const T& rvref(T); #endif // defined(BOOST_ASIO_HAS_MOVE) template char argbyv(T); template struct handler_type_requirements { }; #define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void()) asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \ boost::asio::detail::clvref< \ asio_true_handler_type>(), 0)) == 1, \ "CompletionHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()(), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, std::size_t)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "ReadHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, std::size_t)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "WriteHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0))) == 1, \ "AcceptHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ handler_type, handler, socket_type) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, socket_type)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_move_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "MoveAcceptHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::rvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0))) == 1, \ "ConnectHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ handler_type, handler, endpoint_type) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, endpoint_type)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "RangeConnectHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, iter_type)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "IteratorConnectHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, range_type) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, range_type)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "ResolveHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0))) == 1, \ "WaitHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, int)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "SignalHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0))) == 1, \ "HandshakeHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code, std::size_t)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0), \ static_cast(0))) == 1, \ "BufferedHandshakeHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ \ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ void(boost::system::error_code)) \ asio_true_handler_type; \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ boost::asio::detail::rvref< \ asio_true_handler_type>(), \ static_cast(0))) == 1, \ "ShutdownHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \ boost::asio::detail::lvref< \ asio_true_handler_type>()( \ boost::asio::detail::lvref()), \ char(0))> BOOST_ASIO_UNUSED_TYPEDEF #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) #define BOOST_ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \ handler_type, handler, socket_type) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ typedef int BOOST_ASIO_UNUSED_TYPEDEF #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) } // namespace detail } // namespace asio } // namespace boost #endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP