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 BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
12#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include <boost/asio/detail/config.hpp>
19
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)
28
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)
51
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)
55
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)
75
76namespace boost {
77namespace asio {
78namespace detail {
79
80#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
81
82# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
83
84template <typename Handler>
85auto zero_arg_handler_test(Handler h, void*)
86 -> decltype(
87 sizeof(Handler(static_cast<const Handler&>(h))),
88 ((h)()),
89 char(0));
90
91template <typename Handler>
92char (&zero_arg_handler_test(Handler, ...))[2];
93
94template <typename Handler, typename Arg1>
95auto one_arg_handler_test(Handler h, Arg1* a1)
96 -> decltype(
97 sizeof(Handler(static_cast<const Handler&>(h))),
98 ((h)(*a1)),
99 char(0));
100
101template <typename Handler>
102char (&one_arg_handler_test(Handler h, ...))[2];
103
104template <typename Handler, typename Arg1, typename Arg2>
105auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
106 -> decltype(
107 sizeof(Handler(static_cast<const Handler&>(h))),
108 ((h)(*a1, *a2)),
109 char(0));
110
111template <typename Handler>
112char (&two_arg_handler_test(Handler, ...))[2];
113
114# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
115 static_assert(expr, msg);
116
117# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
118
119# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
120
121# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
122
123template <typename T> T& lvref();
124template <typename T> T& lvref(T);
125template <typename T> const T& clvref();
126template <typename T> const T& clvref(T);
127template <typename T> char argbyv(T);
128
129template <int>
130struct handler_type_requirements
131{
132};
133
134#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
135 handler_type, handler) \
136 \
137 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
138 void()) asio_true_handler_type; \
139 \
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") \
145 \
146 typedef boost::asio::detail::handler_type_requirements< \
147 sizeof( \
148 boost::asio::detail::argbyv( \
149 boost::asio::detail::clvref< \
150 asio_true_handler_type>())) + \
151 sizeof( \
152 boost::asio::detail::lvref< \
153 asio_true_handler_type>()(), \
154 char(0))> BOOST_ASIO_UNUSED_TYPEDEF
155
156#define BOOST_ASIO_READ_HANDLER_CHECK( \
157 handler_type, handler) \
158 \
159 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
160 void(boost::system::error_code, std::size_t)) \
161 asio_true_handler_type; \
162 \
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") \
170 \
171 typedef boost::asio::detail::handler_type_requirements< \
172 sizeof( \
173 boost::asio::detail::argbyv( \
174 boost::asio::detail::clvref< \
175 asio_true_handler_type>())) + \
176 sizeof( \
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
182
183
184#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
185 handler_type, handler) \
186 \
187 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
188 void(boost::system::error_code, std::size_t)) \
189 asio_true_handler_type; \
190 \
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") \
198 \
199 typedef boost::asio::detail::handler_type_requirements< \
200 sizeof( \
201 boost::asio::detail::argbyv( \
202 boost::asio::detail::clvref< \
203 asio_true_handler_type>())) + \
204 sizeof( \
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
210
211#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
212 handler_type, handler) \
213 \
214 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
215 void(boost::system::error_code)) \
216 asio_true_handler_type; \
217 \
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") \
224 \
225 typedef boost::asio::detail::handler_type_requirements< \
226 sizeof( \
227 boost::asio::detail::argbyv( \
228 boost::asio::detail::clvref< \
229 asio_true_handler_type>())) + \
230 sizeof( \
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
235
236#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
237 handler_type, handler) \
238 \
239 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
240 void(boost::system::error_code)) \
241 asio_true_handler_type; \
242 \
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") \
249 \
250 typedef boost::asio::detail::handler_type_requirements< \
251 sizeof( \
252 boost::asio::detail::argbyv( \
253 boost::asio::detail::clvref< \
254 asio_true_handler_type>())) + \
255 sizeof( \
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
260
261#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
262 handler_type, handler, iter_type) \
263 \
264 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
265 void(boost::system::error_code, iter_type)) \
266 asio_true_handler_type; \
267 \
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") \
275 \
276 typedef boost::asio::detail::handler_type_requirements< \
277 sizeof( \
278 boost::asio::detail::argbyv( \
279 boost::asio::detail::clvref< \
280 asio_true_handler_type>())) + \
281 sizeof( \
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
287
288#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
289 handler_type, handler, iter_type) \
290 \
291 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
292 void(boost::system::error_code, iter_type)) \
293 asio_true_handler_type; \
294 \
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") \
302 \
303 typedef boost::asio::detail::handler_type_requirements< \
304 sizeof( \
305 boost::asio::detail::argbyv( \
306 boost::asio::detail::clvref< \
307 asio_true_handler_type>())) + \
308 sizeof( \
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
314
315#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
316 handler_type, handler) \
317 \
318 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
319 void(boost::system::error_code)) \
320 asio_true_handler_type; \
321 \
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") \
328 \
329 typedef boost::asio::detail::handler_type_requirements< \
330 sizeof( \
331 boost::asio::detail::argbyv( \
332 boost::asio::detail::clvref< \
333 asio_true_handler_type>())) + \
334 sizeof( \
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
339
340#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
341 handler_type, handler) \
342 \
343 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
344 void(boost::system::error_code, int)) \
345 asio_true_handler_type; \
346 \
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") \
354 \
355 typedef boost::asio::detail::handler_type_requirements< \
356 sizeof( \
357 boost::asio::detail::argbyv( \
358 boost::asio::detail::clvref< \
359 asio_true_handler_type>())) + \
360 sizeof( \
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
366
367#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
368 handler_type, handler) \
369 \
370 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
371 void(boost::system::error_code)) \
372 asio_true_handler_type; \
373 \
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") \
380 \
381 typedef boost::asio::detail::handler_type_requirements< \
382 sizeof( \
383 boost::asio::detail::argbyv( \
384 boost::asio::detail::clvref< \
385 asio_true_handler_type>())) + \
386 sizeof( \
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
391
392#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
393 handler_type, handler) \
394 \
395 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
396 void(boost::system::error_code, std::size_t)) \
397 asio_true_handler_type; \
398 \
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") \
406 \
407 typedef boost::asio::detail::handler_type_requirements< \
408 sizeof( \
409 boost::asio::detail::argbyv( \
410 boost::asio::detail::clvref< \
411 asio_true_handler_type>())) + \
412 sizeof( \
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
418
419#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
420 handler_type, handler) \
421 \
422 typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
423 void(boost::system::error_code)) \
424 asio_true_handler_type; \
425 \
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") \
432 \
433 typedef boost::asio::detail::handler_type_requirements< \
434 sizeof( \
435 boost::asio::detail::argbyv( \
436 boost::asio::detail::clvref< \
437 asio_true_handler_type>())) + \
438 sizeof( \
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
443
444#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
445
446#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
447 handler_type, handler) \
448 typedef int BOOST_ASIO_UNUSED_TYPEDEF
449
450#define BOOST_ASIO_READ_HANDLER_CHECK( \
451 handler_type, handler) \
452 typedef int BOOST_ASIO_UNUSED_TYPEDEF
453
454#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
455 handler_type, handler) \
456 typedef int BOOST_ASIO_UNUSED_TYPEDEF
457
458#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
459 handler_type, handler) \
460 typedef int BOOST_ASIO_UNUSED_TYPEDEF
461
462#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
463 handler_type, handler) \
464 typedef int BOOST_ASIO_UNUSED_TYPEDEF
465
466#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
467 handler_type, handler, iter_type) \
468 typedef int BOOST_ASIO_UNUSED_TYPEDEF
469
470#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
471 handler_type, handler, iter_type) \
472 typedef int BOOST_ASIO_UNUSED_TYPEDEF
473
474#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
475 handler_type, handler) \
476 typedef int BOOST_ASIO_UNUSED_TYPEDEF
477
478#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
479 handler_type, handler) \
480 typedef int BOOST_ASIO_UNUSED_TYPEDEF
481
482#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
483 handler_type, handler) \
484 typedef int BOOST_ASIO_UNUSED_TYPEDEF
485
486#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
487 handler_type, handler) \
488 typedef int BOOST_ASIO_UNUSED_TYPEDEF
489
490#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
491 handler_type, handler) \
492 typedef int BOOST_ASIO_UNUSED_TYPEDEF
493
494#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
495
496} // namespace detail
497} // namespace asio
498} // namespace boost
499
500#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
501