1 // 2 // detail/handler_type_requirements.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP 12 #define ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP 13 14 15 #include "asio/detail/config.hpp" 16 17 // Older versions of gcc have difficulty compiling the sizeof expressions where 18 // we test the handler type requirements. We'll disable checking of handler type 19 // requirements for those compilers, but otherwise enable it by default. 20 #if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) 21 # if !defined(__GNUC__) || (__GNUC__ >= 4) 22 # define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 23 # endif // !defined(__GNUC__) || (__GNUC__ >= 4) 24 #endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) 25 26 // With C++0x we can use a combination of enhanced SFINAE and static_assert to 27 // generate better template error messages. As this technique is not yet widely 28 // portable, we'll only enable it for tested compilers. 29 #if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) 30 # if defined(__GNUC__) 31 # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) 32 # if defined(__GXX_EXPERIMENTAL_CXX0X__) 33 # define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 34 # endif // defined(__GXX_EXPERIMENTAL_CXX0X__) 35 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) 36 # endif // defined(__GNUC__) 37 # if __has_feature(__cxx_static_assert__) 38 # define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 39 # endif // __has_feature(cxx_static_assert) 40 #endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) 41 42 #if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 43 # include "asio/handler_type.hpp" 44 #endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 45 46 // Newer gcc needs special treatment to suppress unused typedef warnings. 47 #if defined(__GNUC__) 48 # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) 49 # define ASIO_UNUSED_TYPEDEF __attribute__((__unused__)) 50 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) 51 #endif // defined(__GNUC__) 52 #if !defined(ASIO_UNUSED_TYPEDEF) 53 # define ASIO_UNUSED_TYPEDEF 54 #endif // !defined(ASIO_UNUSED_TYPEDEF) 55 56 namespace asio { 57 namespace detail { 58 59 #if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 60 61 # if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) 62 63 template <typename Handler> 64 auto zero_arg_handler_test(Handler h, void*) 65 -> decltype( 66 sizeof(Handler(static_cast<const Handler&>(h))), 67 ((h)()), 68 char(0)); 69 70 template <typename Handler> 71 char (&zero_arg_handler_test(Handler, ...))[2]; 72 73 template <typename Handler, typename Arg1> 74 auto one_arg_handler_test(Handler h, Arg1* a1) 75 -> decltype( 76 sizeof(Handler(static_cast<const Handler&>(h))), 77 ((h)(*a1)), 78 char(0)); 79 80 template <typename Handler> 81 char (&one_arg_handler_test(Handler h, ...))[2]; 82 83 template <typename Handler, typename Arg1, typename Arg2> 84 auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) 85 -> decltype( 86 sizeof(Handler(static_cast<const Handler&>(h))), 87 ((h)(*a1, *a2)), 88 char(0)); 89 90 template <typename Handler> 91 char (&two_arg_handler_test(Handler, ...))[2]; 92 93 # define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) static_assert(expr, msg); 94 95 # else // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) 96 97 # define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) 98 99 # endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) 100 101 template <typename T> T& lvref(); 102 template <typename T> T& lvref(T); 103 template <typename T> const T& clvref(); 104 template <typename T> const T& clvref(T); 105 template <typename T> char argbyv(T); 106 107 template <int> 108 struct handler_type_requirements 109 { 110 }; 111 112 #define ASIO_COMPLETION_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void()) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::zero_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), 0)) == 1, "CompletionHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()(), char(0))> ASIO_UNUSED_TYPEDEF 113 114 #define ASIO_READ_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "ReadHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF 115 116 117 #define ASIO_WRITE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "WriteHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF 118 119 #define ASIO_ACCEPT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "AcceptHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF 120 121 #define ASIO_CONNECT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "ConnectHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF 122 123 #define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( handler_type, handler, iter_type) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, iter_type)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const iter_type*>(0))) == 1, "ComposedConnectHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const iter_type>()), char(0))> ASIO_UNUSED_TYPEDEF 124 125 #define ASIO_RESOLVE_HANDLER_CHECK( handler_type, handler, iter_type) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, iter_type)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const iter_type*>(0))) == 1, "ResolveHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const iter_type>()), char(0))> ASIO_UNUSED_TYPEDEF 126 127 #define ASIO_WAIT_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "WaitHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF 128 129 #define ASIO_SIGNAL_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, int)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const int*>(0))) == 1, "SignalHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const int>()), char(0))> ASIO_UNUSED_TYPEDEF 130 131 #define ASIO_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "HandshakeHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF 132 133 #define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code, std::size_t)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::two_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0), static_cast<const std::size_t*>(0))) == 1, "BufferedHandshakeHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>(), asio::detail::lvref<const std::size_t>()), char(0))> ASIO_UNUSED_TYPEDEF 134 135 #define ASIO_SHUTDOWN_HANDLER_CHECK( handler_type, handler) typedef ASIO_HANDLER_TYPE(handler_type, void(asio::error_code)) asio_true_handler_type; ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( sizeof(asio::detail::one_arg_handler_test( asio::detail::clvref< asio_true_handler_type>(), static_cast<const asio::error_code*>(0))) == 1, "ShutdownHandler type requirements not met") typedef asio::detail::handler_type_requirements< sizeof( asio::detail::argbyv( asio::detail::clvref< asio_true_handler_type>())) + sizeof( asio::detail::lvref< asio_true_handler_type>()( asio::detail::lvref<const asio::error_code>()), char(0))> ASIO_UNUSED_TYPEDEF 136 137 #else // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 138 139 #define ASIO_COMPLETION_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 140 141 #define ASIO_READ_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 142 143 #define ASIO_WRITE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 144 145 #define ASIO_ACCEPT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 146 147 #define ASIO_CONNECT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 148 149 #define ASIO_COMPOSED_CONNECT_HANDLER_CHECK( handler_type, handler, iter_type) typedef int ASIO_UNUSED_TYPEDEF 150 151 #define ASIO_RESOLVE_HANDLER_CHECK( handler_type, handler, iter_type) typedef int ASIO_UNUSED_TYPEDEF 152 153 #define ASIO_WAIT_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 154 155 #define ASIO_SIGNAL_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 156 157 #define ASIO_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 158 159 #define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 160 161 #define ASIO_SHUTDOWN_HANDLER_CHECK( handler_type, handler) typedef int ASIO_UNUSED_TYPEDEF 162 163 #endif // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 164 165 } // namespace detail 166 } // namespace asio 167 168 #endif // ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP 169