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