2 // detail/handler_type_requirements.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
12 #define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 // Older versions of gcc have difficulty compiling the sizeof expressions where
21 // we test the handler type requirements. We'll disable checking of handler type
22 // requirements for those compilers, but otherwise enable it by default.
23 #if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
24 # if !defined(__GNUC__) || (__GNUC__ >= 4)
25 # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1
26 # endif // !defined(__GNUC__) || (__GNUC__ >= 4)
27 #endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
29 // With C++0x we can use a combination of enhanced SFINAE and static_assert to
30 // generate better template error messages. As this technique is not yet widely
31 // portable, we'll only enable it for tested compilers.
32 #if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
33 # if defined(__GNUC__)
34 # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
35 # if defined(__GXX_EXPERIMENTAL_CXX0X__)
36 # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
37 # endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
38 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)
39 # endif // defined(__GNUC__)
40 # if defined(BOOST_ASIO_MSVC)
41 # if (_MSC_VER >= 1600)
42 # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
43 # endif // (_MSC_VER >= 1600)
44 # endif // defined(BOOST_ASIO_MSVC)
45 # if defined(__clang__)
46 # if __has_feature(__cxx_static_assert__)
47 # define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1
48 # endif // __has_feature(cxx_static_assert)
49 # endif // defined(__clang__)
50 #endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
52 #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
53 # include <boost/asio/handler_type.hpp>
54 #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
56 // Newer gcc needs special treatment to suppress unused typedef warnings.
58 # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
59 # define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
60 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
61 #endif // defined(__GNUC__)
62 #if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
63 # define BOOST_ASIO_UNUSED_TYPEDEF
64 #endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
70 #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
72 # if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
74 template <typename Handler>
75 auto zero_arg_handler_test(Handler h, void*)
77 sizeof(Handler(static_cast<const Handler&>(h))),
81 template <typename Handler>
82 char (&zero_arg_handler_test(Handler, ...))[2];
84 template <typename Handler, typename Arg1>
85 auto one_arg_handler_test(Handler h, Arg1* a1)
87 sizeof(Handler(static_cast<const Handler&>(h))),
91 template <typename Handler>
92 char (&one_arg_handler_test(Handler h, ...))[2];
94 template <typename Handler, typename Arg1, typename Arg2>
95 auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
97 sizeof(Handler(static_cast<const Handler&>(h))),
101 template <typename Handler>
102 char (&two_arg_handler_test(Handler, ...))[2];
104 # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
105 static_assert(expr, msg);
107 # else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
109 # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
111 # endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
113 template <typename T> T& lvref();
114 template <typename T> T& lvref(T);
115 template <typename T> const T& clvref();
116 template <typename T> const T& clvref(T);
117 template <typename T> char argbyv(T);
120 struct handler_type_requirements
124 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
125 handler_type, handler) \
127 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
128 void()) asio_true_handler_type; \
130 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
131 sizeof(boost::asio::detail::zero_arg_handler_test( \
132 boost::asio::detail::clvref< \
133 asio_true_handler_type>(), 0)) == 1, \
134 "CompletionHandler type requirements not met") \
136 typedef boost::asio::detail::handler_type_requirements< \
138 boost::asio::detail::argbyv( \
139 boost::asio::detail::clvref< \
140 asio_true_handler_type>())) + \
142 boost::asio::detail::lvref< \
143 asio_true_handler_type>()(), \
144 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
146 #define BOOST_ASIO_READ_HANDLER_CHECK( \
147 handler_type, handler) \
149 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
150 void(boost::system::error_code, std::size_t)) \
151 asio_true_handler_type; \
153 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
154 sizeof(boost::asio::detail::two_arg_handler_test( \
155 boost::asio::detail::clvref< \
156 asio_true_handler_type>(), \
157 static_cast<const boost::system::error_code*>(0), \
158 static_cast<const std::size_t*>(0))) == 1, \
159 "ReadHandler type requirements not met") \
161 typedef boost::asio::detail::handler_type_requirements< \
163 boost::asio::detail::argbyv( \
164 boost::asio::detail::clvref< \
165 asio_true_handler_type>())) + \
167 boost::asio::detail::lvref< \
168 asio_true_handler_type>()( \
169 boost::asio::detail::lvref<const boost::system::error_code>(), \
170 boost::asio::detail::lvref<const std::size_t>()), \
171 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
174 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
175 handler_type, handler) \
177 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
178 void(boost::system::error_code, std::size_t)) \
179 asio_true_handler_type; \
181 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
182 sizeof(boost::asio::detail::two_arg_handler_test( \
183 boost::asio::detail::clvref< \
184 asio_true_handler_type>(), \
185 static_cast<const boost::system::error_code*>(0), \
186 static_cast<const std::size_t*>(0))) == 1, \
187 "WriteHandler type requirements not met") \
189 typedef boost::asio::detail::handler_type_requirements< \
191 boost::asio::detail::argbyv( \
192 boost::asio::detail::clvref< \
193 asio_true_handler_type>())) + \
195 boost::asio::detail::lvref< \
196 asio_true_handler_type>()( \
197 boost::asio::detail::lvref<const boost::system::error_code>(), \
198 boost::asio::detail::lvref<const std::size_t>()), \
199 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
201 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
202 handler_type, handler) \
204 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
205 void(boost::system::error_code)) \
206 asio_true_handler_type; \
208 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
209 sizeof(boost::asio::detail::one_arg_handler_test( \
210 boost::asio::detail::clvref< \
211 asio_true_handler_type>(), \
212 static_cast<const boost::system::error_code*>(0))) == 1, \
213 "AcceptHandler type requirements not met") \
215 typedef boost::asio::detail::handler_type_requirements< \
217 boost::asio::detail::argbyv( \
218 boost::asio::detail::clvref< \
219 asio_true_handler_type>())) + \
221 boost::asio::detail::lvref< \
222 asio_true_handler_type>()( \
223 boost::asio::detail::lvref<const boost::system::error_code>()), \
224 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
226 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
227 handler_type, handler) \
229 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
230 void(boost::system::error_code)) \
231 asio_true_handler_type; \
233 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
234 sizeof(boost::asio::detail::one_arg_handler_test( \
235 boost::asio::detail::clvref< \
236 asio_true_handler_type>(), \
237 static_cast<const boost::system::error_code*>(0))) == 1, \
238 "ConnectHandler type requirements not met") \
240 typedef boost::asio::detail::handler_type_requirements< \
242 boost::asio::detail::argbyv( \
243 boost::asio::detail::clvref< \
244 asio_true_handler_type>())) + \
246 boost::asio::detail::lvref< \
247 asio_true_handler_type>()( \
248 boost::asio::detail::lvref<const boost::system::error_code>()), \
249 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
251 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
252 handler_type, handler, iter_type) \
254 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
255 void(boost::system::error_code, iter_type)) \
256 asio_true_handler_type; \
258 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
259 sizeof(boost::asio::detail::two_arg_handler_test( \
260 boost::asio::detail::clvref< \
261 asio_true_handler_type>(), \
262 static_cast<const boost::system::error_code*>(0), \
263 static_cast<const iter_type*>(0))) == 1, \
264 "ComposedConnectHandler type requirements not met") \
266 typedef boost::asio::detail::handler_type_requirements< \
268 boost::asio::detail::argbyv( \
269 boost::asio::detail::clvref< \
270 asio_true_handler_type>())) + \
272 boost::asio::detail::lvref< \
273 asio_true_handler_type>()( \
274 boost::asio::detail::lvref<const boost::system::error_code>(), \
275 boost::asio::detail::lvref<const iter_type>()), \
276 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
278 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
279 handler_type, handler, iter_type) \
281 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
282 void(boost::system::error_code, iter_type)) \
283 asio_true_handler_type; \
285 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
286 sizeof(boost::asio::detail::two_arg_handler_test( \
287 boost::asio::detail::clvref< \
288 asio_true_handler_type>(), \
289 static_cast<const boost::system::error_code*>(0), \
290 static_cast<const iter_type*>(0))) == 1, \
291 "ResolveHandler type requirements not met") \
293 typedef boost::asio::detail::handler_type_requirements< \
295 boost::asio::detail::argbyv( \
296 boost::asio::detail::clvref< \
297 asio_true_handler_type>())) + \
299 boost::asio::detail::lvref< \
300 asio_true_handler_type>()( \
301 boost::asio::detail::lvref<const boost::system::error_code>(), \
302 boost::asio::detail::lvref<const iter_type>()), \
303 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
305 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
306 handler_type, handler) \
308 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
309 void(boost::system::error_code)) \
310 asio_true_handler_type; \
312 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
313 sizeof(boost::asio::detail::one_arg_handler_test( \
314 boost::asio::detail::clvref< \
315 asio_true_handler_type>(), \
316 static_cast<const boost::system::error_code*>(0))) == 1, \
317 "WaitHandler type requirements not met") \
319 typedef boost::asio::detail::handler_type_requirements< \
321 boost::asio::detail::argbyv( \
322 boost::asio::detail::clvref< \
323 asio_true_handler_type>())) + \
325 boost::asio::detail::lvref< \
326 asio_true_handler_type>()( \
327 boost::asio::detail::lvref<const boost::system::error_code>()), \
328 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
330 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
331 handler_type, handler) \
333 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
334 void(boost::system::error_code, int)) \
335 asio_true_handler_type; \
337 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
338 sizeof(boost::asio::detail::two_arg_handler_test( \
339 boost::asio::detail::clvref< \
340 asio_true_handler_type>(), \
341 static_cast<const boost::system::error_code*>(0), \
342 static_cast<const int*>(0))) == 1, \
343 "SignalHandler type requirements not met") \
345 typedef boost::asio::detail::handler_type_requirements< \
347 boost::asio::detail::argbyv( \
348 boost::asio::detail::clvref< \
349 asio_true_handler_type>())) + \
351 boost::asio::detail::lvref< \
352 asio_true_handler_type>()( \
353 boost::asio::detail::lvref<const boost::system::error_code>(), \
354 boost::asio::detail::lvref<const int>()), \
355 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
357 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
358 handler_type, handler) \
360 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
361 void(boost::system::error_code)) \
362 asio_true_handler_type; \
364 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
365 sizeof(boost::asio::detail::one_arg_handler_test( \
366 boost::asio::detail::clvref< \
367 asio_true_handler_type>(), \
368 static_cast<const boost::system::error_code*>(0))) == 1, \
369 "HandshakeHandler type requirements not met") \
371 typedef boost::asio::detail::handler_type_requirements< \
373 boost::asio::detail::argbyv( \
374 boost::asio::detail::clvref< \
375 asio_true_handler_type>())) + \
377 boost::asio::detail::lvref< \
378 asio_true_handler_type>()( \
379 boost::asio::detail::lvref<const boost::system::error_code>()), \
380 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
382 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
383 handler_type, handler) \
385 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
386 void(boost::system::error_code, std::size_t)) \
387 asio_true_handler_type; \
389 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
390 sizeof(boost::asio::detail::two_arg_handler_test( \
391 boost::asio::detail::clvref< \
392 asio_true_handler_type>(), \
393 static_cast<const boost::system::error_code*>(0), \
394 static_cast<const std::size_t*>(0))) == 1, \
395 "BufferedHandshakeHandler type requirements not met") \
397 typedef boost::asio::detail::handler_type_requirements< \
399 boost::asio::detail::argbyv( \
400 boost::asio::detail::clvref< \
401 asio_true_handler_type>())) + \
403 boost::asio::detail::lvref< \
404 asio_true_handler_type>()( \
405 boost::asio::detail::lvref<const boost::system::error_code>(), \
406 boost::asio::detail::lvref<const std::size_t>()), \
407 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
409 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
410 handler_type, handler) \
412 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
413 void(boost::system::error_code)) \
414 asio_true_handler_type; \
416 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
417 sizeof(boost::asio::detail::one_arg_handler_test( \
418 boost::asio::detail::clvref< \
419 asio_true_handler_type>(), \
420 static_cast<const boost::system::error_code*>(0))) == 1, \
421 "ShutdownHandler type requirements not met") \
423 typedef boost::asio::detail::handler_type_requirements< \
425 boost::asio::detail::argbyv( \
426 boost::asio::detail::clvref< \
427 asio_true_handler_type>())) + \
429 boost::asio::detail::lvref< \
430 asio_true_handler_type>()( \
431 boost::asio::detail::lvref<const boost::system::error_code>()), \
432 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
434 #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
436 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
437 handler_type, handler) \
438 typedef int BOOST_ASIO_UNUSED_TYPEDEF
440 #define BOOST_ASIO_READ_HANDLER_CHECK( \
441 handler_type, handler) \
442 typedef int BOOST_ASIO_UNUSED_TYPEDEF
444 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
445 handler_type, handler) \
446 typedef int BOOST_ASIO_UNUSED_TYPEDEF
448 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
449 handler_type, handler) \
450 typedef int BOOST_ASIO_UNUSED_TYPEDEF
452 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
453 handler_type, handler) \
454 typedef int BOOST_ASIO_UNUSED_TYPEDEF
456 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
457 handler_type, handler, iter_type) \
458 typedef int BOOST_ASIO_UNUSED_TYPEDEF
460 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
461 handler_type, handler, iter_type) \
462 typedef int BOOST_ASIO_UNUSED_TYPEDEF
464 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
465 handler_type, handler) \
466 typedef int BOOST_ASIO_UNUSED_TYPEDEF
468 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
469 handler_type, handler) \
470 typedef int BOOST_ASIO_UNUSED_TYPEDEF
472 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
473 handler_type, handler) \
474 typedef int BOOST_ASIO_UNUSED_TYPEDEF
476 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
477 handler_type, handler) \
478 typedef int BOOST_ASIO_UNUSED_TYPEDEF
480 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
481 handler_type, handler) \
482 typedef int BOOST_ASIO_UNUSED_TYPEDEF
484 #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
486 } // namespace detail
490 #endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP