2 // detail/handler_type_requirements.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2016 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, clang need special treatment to suppress unused typedef warnings.
57 #if defined(__clang__)
58 # if defined(__apple_build_version__)
59 # if (__clang_major__ >= 7)
60 # define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
61 # endif // (__clang_major__ >= 7)
62 # elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \
63 || (__clang_major__ > 3)
64 # define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
65 # endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))
66 // || (__clang_major__ > 3)
67 #elif defined(__GNUC__)
68 # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
69 # define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__))
70 # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)
71 #endif // defined(__GNUC__)
72 #if !defined(BOOST_ASIO_UNUSED_TYPEDEF)
73 # define BOOST_ASIO_UNUSED_TYPEDEF
74 #endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF)
80 #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
82 # if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
84 template <typename Handler>
85 auto zero_arg_handler_test(Handler h, void*)
87 sizeof(Handler(static_cast<const Handler&>(h))),
91 template <typename Handler>
92 char (&zero_arg_handler_test(Handler, ...))[2];
94 template <typename Handler, typename Arg1>
95 auto one_arg_handler_test(Handler h, Arg1* a1)
97 sizeof(Handler(static_cast<const Handler&>(h))),
101 template <typename Handler>
102 char (&one_arg_handler_test(Handler h, ...))[2];
104 template <typename Handler, typename Arg1, typename Arg2>
105 auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
107 sizeof(Handler(static_cast<const Handler&>(h))),
111 template <typename Handler>
112 char (&two_arg_handler_test(Handler, ...))[2];
114 # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
115 static_assert(expr, msg);
117 # else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
119 # define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
121 # endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
123 template <typename T> T& lvref();
124 template <typename T> T& lvref(T);
125 template <typename T> const T& clvref();
126 template <typename T> const T& clvref(T);
127 template <typename T> char argbyv(T);
130 struct handler_type_requirements
134 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
135 handler_type, handler) \
137 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
138 void()) asio_true_handler_type; \
140 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
141 sizeof(boost::asio::detail::zero_arg_handler_test( \
142 boost::asio::detail::clvref< \
143 asio_true_handler_type>(), 0)) == 1, \
144 "CompletionHandler type requirements not met") \
146 typedef boost::asio::detail::handler_type_requirements< \
148 boost::asio::detail::argbyv( \
149 boost::asio::detail::clvref< \
150 asio_true_handler_type>())) + \
152 boost::asio::detail::lvref< \
153 asio_true_handler_type>()(), \
154 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
156 #define BOOST_ASIO_READ_HANDLER_CHECK( \
157 handler_type, handler) \
159 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
160 void(boost::system::error_code, std::size_t)) \
161 asio_true_handler_type; \
163 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
164 sizeof(boost::asio::detail::two_arg_handler_test( \
165 boost::asio::detail::clvref< \
166 asio_true_handler_type>(), \
167 static_cast<const boost::system::error_code*>(0), \
168 static_cast<const std::size_t*>(0))) == 1, \
169 "ReadHandler type requirements not met") \
171 typedef boost::asio::detail::handler_type_requirements< \
173 boost::asio::detail::argbyv( \
174 boost::asio::detail::clvref< \
175 asio_true_handler_type>())) + \
177 boost::asio::detail::lvref< \
178 asio_true_handler_type>()( \
179 boost::asio::detail::lvref<const boost::system::error_code>(), \
180 boost::asio::detail::lvref<const std::size_t>()), \
181 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
184 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
185 handler_type, handler) \
187 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
188 void(boost::system::error_code, std::size_t)) \
189 asio_true_handler_type; \
191 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
192 sizeof(boost::asio::detail::two_arg_handler_test( \
193 boost::asio::detail::clvref< \
194 asio_true_handler_type>(), \
195 static_cast<const boost::system::error_code*>(0), \
196 static_cast<const std::size_t*>(0))) == 1, \
197 "WriteHandler type requirements not met") \
199 typedef boost::asio::detail::handler_type_requirements< \
201 boost::asio::detail::argbyv( \
202 boost::asio::detail::clvref< \
203 asio_true_handler_type>())) + \
205 boost::asio::detail::lvref< \
206 asio_true_handler_type>()( \
207 boost::asio::detail::lvref<const boost::system::error_code>(), \
208 boost::asio::detail::lvref<const std::size_t>()), \
209 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
211 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
212 handler_type, handler) \
214 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
215 void(boost::system::error_code)) \
216 asio_true_handler_type; \
218 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
219 sizeof(boost::asio::detail::one_arg_handler_test( \
220 boost::asio::detail::clvref< \
221 asio_true_handler_type>(), \
222 static_cast<const boost::system::error_code*>(0))) == 1, \
223 "AcceptHandler type requirements not met") \
225 typedef boost::asio::detail::handler_type_requirements< \
227 boost::asio::detail::argbyv( \
228 boost::asio::detail::clvref< \
229 asio_true_handler_type>())) + \
231 boost::asio::detail::lvref< \
232 asio_true_handler_type>()( \
233 boost::asio::detail::lvref<const boost::system::error_code>()), \
234 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
236 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
237 handler_type, handler) \
239 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
240 void(boost::system::error_code)) \
241 asio_true_handler_type; \
243 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
244 sizeof(boost::asio::detail::one_arg_handler_test( \
245 boost::asio::detail::clvref< \
246 asio_true_handler_type>(), \
247 static_cast<const boost::system::error_code*>(0))) == 1, \
248 "ConnectHandler type requirements not met") \
250 typedef boost::asio::detail::handler_type_requirements< \
252 boost::asio::detail::argbyv( \
253 boost::asio::detail::clvref< \
254 asio_true_handler_type>())) + \
256 boost::asio::detail::lvref< \
257 asio_true_handler_type>()( \
258 boost::asio::detail::lvref<const boost::system::error_code>()), \
259 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
261 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
262 handler_type, handler, iter_type) \
264 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
265 void(boost::system::error_code, iter_type)) \
266 asio_true_handler_type; \
268 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
269 sizeof(boost::asio::detail::two_arg_handler_test( \
270 boost::asio::detail::clvref< \
271 asio_true_handler_type>(), \
272 static_cast<const boost::system::error_code*>(0), \
273 static_cast<const iter_type*>(0))) == 1, \
274 "ComposedConnectHandler type requirements not met") \
276 typedef boost::asio::detail::handler_type_requirements< \
278 boost::asio::detail::argbyv( \
279 boost::asio::detail::clvref< \
280 asio_true_handler_type>())) + \
282 boost::asio::detail::lvref< \
283 asio_true_handler_type>()( \
284 boost::asio::detail::lvref<const boost::system::error_code>(), \
285 boost::asio::detail::lvref<const iter_type>()), \
286 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
288 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
289 handler_type, handler, iter_type) \
291 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
292 void(boost::system::error_code, iter_type)) \
293 asio_true_handler_type; \
295 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
296 sizeof(boost::asio::detail::two_arg_handler_test( \
297 boost::asio::detail::clvref< \
298 asio_true_handler_type>(), \
299 static_cast<const boost::system::error_code*>(0), \
300 static_cast<const iter_type*>(0))) == 1, \
301 "ResolveHandler type requirements not met") \
303 typedef boost::asio::detail::handler_type_requirements< \
305 boost::asio::detail::argbyv( \
306 boost::asio::detail::clvref< \
307 asio_true_handler_type>())) + \
309 boost::asio::detail::lvref< \
310 asio_true_handler_type>()( \
311 boost::asio::detail::lvref<const boost::system::error_code>(), \
312 boost::asio::detail::lvref<const iter_type>()), \
313 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
315 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
316 handler_type, handler) \
318 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
319 void(boost::system::error_code)) \
320 asio_true_handler_type; \
322 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
323 sizeof(boost::asio::detail::one_arg_handler_test( \
324 boost::asio::detail::clvref< \
325 asio_true_handler_type>(), \
326 static_cast<const boost::system::error_code*>(0))) == 1, \
327 "WaitHandler type requirements not met") \
329 typedef boost::asio::detail::handler_type_requirements< \
331 boost::asio::detail::argbyv( \
332 boost::asio::detail::clvref< \
333 asio_true_handler_type>())) + \
335 boost::asio::detail::lvref< \
336 asio_true_handler_type>()( \
337 boost::asio::detail::lvref<const boost::system::error_code>()), \
338 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
340 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
341 handler_type, handler) \
343 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
344 void(boost::system::error_code, int)) \
345 asio_true_handler_type; \
347 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
348 sizeof(boost::asio::detail::two_arg_handler_test( \
349 boost::asio::detail::clvref< \
350 asio_true_handler_type>(), \
351 static_cast<const boost::system::error_code*>(0), \
352 static_cast<const int*>(0))) == 1, \
353 "SignalHandler type requirements not met") \
355 typedef boost::asio::detail::handler_type_requirements< \
357 boost::asio::detail::argbyv( \
358 boost::asio::detail::clvref< \
359 asio_true_handler_type>())) + \
361 boost::asio::detail::lvref< \
362 asio_true_handler_type>()( \
363 boost::asio::detail::lvref<const boost::system::error_code>(), \
364 boost::asio::detail::lvref<const int>()), \
365 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
367 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
368 handler_type, handler) \
370 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
371 void(boost::system::error_code)) \
372 asio_true_handler_type; \
374 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
375 sizeof(boost::asio::detail::one_arg_handler_test( \
376 boost::asio::detail::clvref< \
377 asio_true_handler_type>(), \
378 static_cast<const boost::system::error_code*>(0))) == 1, \
379 "HandshakeHandler type requirements not met") \
381 typedef boost::asio::detail::handler_type_requirements< \
383 boost::asio::detail::argbyv( \
384 boost::asio::detail::clvref< \
385 asio_true_handler_type>())) + \
387 boost::asio::detail::lvref< \
388 asio_true_handler_type>()( \
389 boost::asio::detail::lvref<const boost::system::error_code>()), \
390 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
392 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
393 handler_type, handler) \
395 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
396 void(boost::system::error_code, std::size_t)) \
397 asio_true_handler_type; \
399 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
400 sizeof(boost::asio::detail::two_arg_handler_test( \
401 boost::asio::detail::clvref< \
402 asio_true_handler_type>(), \
403 static_cast<const boost::system::error_code*>(0), \
404 static_cast<const std::size_t*>(0))) == 1, \
405 "BufferedHandshakeHandler type requirements not met") \
407 typedef boost::asio::detail::handler_type_requirements< \
409 boost::asio::detail::argbyv( \
410 boost::asio::detail::clvref< \
411 asio_true_handler_type>())) + \
413 boost::asio::detail::lvref< \
414 asio_true_handler_type>()( \
415 boost::asio::detail::lvref<const boost::system::error_code>(), \
416 boost::asio::detail::lvref<const std::size_t>()), \
417 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
419 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
420 handler_type, handler) \
422 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
423 void(boost::system::error_code)) \
424 asio_true_handler_type; \
426 BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
427 sizeof(boost::asio::detail::one_arg_handler_test( \
428 boost::asio::detail::clvref< \
429 asio_true_handler_type>(), \
430 static_cast<const boost::system::error_code*>(0))) == 1, \
431 "ShutdownHandler type requirements not met") \
433 typedef boost::asio::detail::handler_type_requirements< \
435 boost::asio::detail::argbyv( \
436 boost::asio::detail::clvref< \
437 asio_true_handler_type>())) + \
439 boost::asio::detail::lvref< \
440 asio_true_handler_type>()( \
441 boost::asio::detail::lvref<const boost::system::error_code>()), \
442 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
444 #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
446 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
447 handler_type, handler) \
448 typedef int BOOST_ASIO_UNUSED_TYPEDEF
450 #define BOOST_ASIO_READ_HANDLER_CHECK( \
451 handler_type, handler) \
452 typedef int BOOST_ASIO_UNUSED_TYPEDEF
454 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
455 handler_type, handler) \
456 typedef int BOOST_ASIO_UNUSED_TYPEDEF
458 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
459 handler_type, handler) \
460 typedef int BOOST_ASIO_UNUSED_TYPEDEF
462 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
463 handler_type, handler) \
464 typedef int BOOST_ASIO_UNUSED_TYPEDEF
466 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
467 handler_type, handler, iter_type) \
468 typedef int BOOST_ASIO_UNUSED_TYPEDEF
470 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
471 handler_type, handler, iter_type) \
472 typedef int BOOST_ASIO_UNUSED_TYPEDEF
474 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
475 handler_type, handler) \
476 typedef int BOOST_ASIO_UNUSED_TYPEDEF
478 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
479 handler_type, handler) \
480 typedef int BOOST_ASIO_UNUSED_TYPEDEF
482 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
483 handler_type, handler) \
484 typedef int BOOST_ASIO_UNUSED_TYPEDEF
486 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
487 handler_type, handler) \
488 typedef int BOOST_ASIO_UNUSED_TYPEDEF
490 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
491 handler_type, handler) \
492 typedef int BOOST_ASIO_UNUSED_TYPEDEF
494 #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
496 } // namespace detail
500 #endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP