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 56namespace asio { 57namespace detail { 58 59#if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) 60 61# if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) 62 63template <typename Handler> 64auto zero_arg_handler_test(Handler h, void*) 65 -> decltype( 66 sizeof(Handler(static_cast<const Handler&>(h))), 67 ((h)()), 68 char(0)); 69 70template <typename Handler> 71char (&zero_arg_handler_test(Handler, ...))[2]; 72 73template <typename Handler, typename Arg1> 74auto 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 80template <typename Handler> 81char (&one_arg_handler_test(Handler h, ...))[2]; 82 83template <typename Handler, typename Arg1, typename Arg2> 84auto 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 90template <typename Handler> 91char (&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 101template <typename T> T& lvref(); 102template <typename T> T& lvref(T); 103template <typename T> const T& clvref(); 104template <typename T> const T& clvref(T); 105template <typename T> char argbyv(T); 106 107template <int> 108struct 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