// // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2012 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_MSVC) # if (_MSC_VER >= 1600) # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 # endif // (_MSC_VER >= 1600) # endif // defined(BOOST_MSVC) #endif // !defined(BOOST_ASIO_DISABLE_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_handler_test(Handler h, void*) -> decltype( sizeof(Handler(static_cast(h))), ((h)()), char(0)); template char (&zero_arg_handler_test(Handler, ...))[2]; template auto one_arg_handler_test(Handler h, Arg1* a1) -> decltype( sizeof(Handler(static_cast(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(static_cast(h))), ((h)(*a1, *a2)), char(0)); template char (&two_arg_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(T); template char argbyv(T); template struct handler_type_requirements { }; #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::zero_arg_handler_test( \ handler, 0)) == 1, \ "CompletionHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)(), \ char(0))> #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ handler, \ 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::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ handler, \ 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::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ handler, \ static_cast(0))) == 1, \ "AcceptHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ handler, \ static_cast(0))) == 1, \ "ConnectHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ handler, \ static_cast(0), \ static_cast(0))) == 1, \ "ComposedConnectHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, iter_type) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ handler, \ 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::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ handler, \ static_cast(0))) == 1, \ "WaitHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::two_arg_handler_test( \ handler, \ 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::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref(), \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ handler, \ static_cast(0))) == 1, \ "HandshakeHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref()), \ char(0))> #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ \ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ sizeof(boost::asio::detail::one_arg_handler_test( \ handler, \ static_cast(0))) == 1, \ "ShutdownHandler type requirements not met") \ \ typedef boost::asio::detail::handler_type_requirements< \ sizeof( \ boost::asio::detail::argbyv( \ boost::asio::detail::clvref(handler))) + \ sizeof( \ boost::asio::detail::lvref(handler)( \ boost::asio::detail::lvref()), \ char(0))> #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_READ_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_WRITE_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ handler_type, handler, iter_type) \ typedef int #define BOOST_ASIO_WAIT_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ handler_type, handler) \ typedef int #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ handler_type, handler) \ typedef int #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) } // namespace detail } // namespace asio } // namespace boost #endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP