Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / asio / detail / handler_type_requirements.hpp
1 //
2 // detail/handler_type_requirements.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2014 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 needs special treatment to suppress unused typedef warnings.
57 #if defined(__GNUC__)
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)
65
66 namespace boost {
67 namespace asio {
68 namespace detail {
69
70 #if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
71
72 # if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
73
74 template <typename Handler>
75 auto zero_arg_handler_test(Handler h, void*)
76   -> decltype(
77     sizeof(Handler(static_cast<const Handler&>(h))),
78     ((h)()),
79     char(0));
80
81 template <typename Handler>
82 char (&zero_arg_handler_test(Handler, ...))[2];
83
84 template <typename Handler, typename Arg1>
85 auto one_arg_handler_test(Handler h, Arg1* a1)
86   -> decltype(
87     sizeof(Handler(static_cast<const Handler&>(h))),
88     ((h)(*a1)),
89     char(0));
90
91 template <typename Handler>
92 char (&one_arg_handler_test(Handler h, ...))[2];
93
94 template <typename Handler, typename Arg1, typename Arg2>
95 auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
96   -> decltype(
97     sizeof(Handler(static_cast<const Handler&>(h))),
98     ((h)(*a1, *a2)),
99     char(0));
100
101 template <typename Handler>
102 char (&two_arg_handler_test(Handler, ...))[2];
103
104 #  define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
105      static_assert(expr, msg);
106
107 # else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
108
109 #  define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)
110
111 # endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
112
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);
118
119 template <int>
120 struct handler_type_requirements
121 {
122 };
123
124 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
125     handler_type, handler) \
126   \
127   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
128       void()) asio_true_handler_type; \
129   \
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") \
135   \
136   typedef boost::asio::detail::handler_type_requirements< \
137       sizeof( \
138         boost::asio::detail::argbyv( \
139           boost::asio::detail::clvref< \
140             asio_true_handler_type>())) + \
141       sizeof( \
142         boost::asio::detail::lvref< \
143           asio_true_handler_type>()(), \
144         char(0))> BOOST_ASIO_UNUSED_TYPEDEF
145
146 #define BOOST_ASIO_READ_HANDLER_CHECK( \
147     handler_type, handler) \
148   \
149   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
150       void(boost::system::error_code, std::size_t)) \
151     asio_true_handler_type; \
152   \
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") \
160   \
161   typedef boost::asio::detail::handler_type_requirements< \
162       sizeof( \
163         boost::asio::detail::argbyv( \
164           boost::asio::detail::clvref< \
165             asio_true_handler_type>())) + \
166       sizeof( \
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
172
173
174 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
175     handler_type, handler) \
176   \
177   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
178       void(boost::system::error_code, std::size_t)) \
179     asio_true_handler_type; \
180   \
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") \
188   \
189   typedef boost::asio::detail::handler_type_requirements< \
190       sizeof( \
191         boost::asio::detail::argbyv( \
192           boost::asio::detail::clvref< \
193             asio_true_handler_type>())) + \
194       sizeof( \
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
200
201 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
202     handler_type, handler) \
203   \
204   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
205       void(boost::system::error_code)) \
206     asio_true_handler_type; \
207   \
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") \
214   \
215   typedef boost::asio::detail::handler_type_requirements< \
216       sizeof( \
217         boost::asio::detail::argbyv( \
218           boost::asio::detail::clvref< \
219             asio_true_handler_type>())) + \
220       sizeof( \
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
225
226 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
227     handler_type, handler) \
228   \
229   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
230       void(boost::system::error_code)) \
231     asio_true_handler_type; \
232   \
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") \
239   \
240   typedef boost::asio::detail::handler_type_requirements< \
241       sizeof( \
242         boost::asio::detail::argbyv( \
243           boost::asio::detail::clvref< \
244             asio_true_handler_type>())) + \
245       sizeof( \
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
250
251 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
252     handler_type, handler, iter_type) \
253   \
254   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
255       void(boost::system::error_code, iter_type)) \
256     asio_true_handler_type; \
257   \
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") \
265   \
266   typedef boost::asio::detail::handler_type_requirements< \
267       sizeof( \
268         boost::asio::detail::argbyv( \
269           boost::asio::detail::clvref< \
270             asio_true_handler_type>())) + \
271       sizeof( \
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
277
278 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
279     handler_type, handler, iter_type) \
280   \
281   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
282       void(boost::system::error_code, iter_type)) \
283     asio_true_handler_type; \
284   \
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") \
292   \
293   typedef boost::asio::detail::handler_type_requirements< \
294       sizeof( \
295         boost::asio::detail::argbyv( \
296           boost::asio::detail::clvref< \
297             asio_true_handler_type>())) + \
298       sizeof( \
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
304
305 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
306     handler_type, handler) \
307   \
308   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
309       void(boost::system::error_code)) \
310     asio_true_handler_type; \
311   \
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") \
318   \
319   typedef boost::asio::detail::handler_type_requirements< \
320       sizeof( \
321         boost::asio::detail::argbyv( \
322           boost::asio::detail::clvref< \
323             asio_true_handler_type>())) + \
324       sizeof( \
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
329
330 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
331     handler_type, handler) \
332   \
333   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
334       void(boost::system::error_code, int)) \
335     asio_true_handler_type; \
336   \
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") \
344   \
345   typedef boost::asio::detail::handler_type_requirements< \
346       sizeof( \
347         boost::asio::detail::argbyv( \
348           boost::asio::detail::clvref< \
349             asio_true_handler_type>())) + \
350       sizeof( \
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
356
357 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
358     handler_type, handler) \
359   \
360   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
361       void(boost::system::error_code)) \
362     asio_true_handler_type; \
363   \
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") \
370   \
371   typedef boost::asio::detail::handler_type_requirements< \
372       sizeof( \
373         boost::asio::detail::argbyv( \
374           boost::asio::detail::clvref< \
375             asio_true_handler_type>())) + \
376       sizeof( \
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
381
382 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
383     handler_type, handler) \
384   \
385   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
386       void(boost::system::error_code, std::size_t)) \
387     asio_true_handler_type; \
388   \
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") \
396   \
397   typedef boost::asio::detail::handler_type_requirements< \
398       sizeof( \
399         boost::asio::detail::argbyv( \
400           boost::asio::detail::clvref< \
401             asio_true_handler_type>())) + \
402       sizeof( \
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
408
409 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
410     handler_type, handler) \
411   \
412   typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
413       void(boost::system::error_code)) \
414     asio_true_handler_type; \
415   \
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") \
422   \
423   typedef boost::asio::detail::handler_type_requirements< \
424       sizeof( \
425         boost::asio::detail::argbyv( \
426           boost::asio::detail::clvref< \
427             asio_true_handler_type>())) + \
428       sizeof( \
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
433
434 #else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
435
436 #define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \
437     handler_type, handler) \
438   typedef int BOOST_ASIO_UNUSED_TYPEDEF
439
440 #define BOOST_ASIO_READ_HANDLER_CHECK( \
441     handler_type, handler) \
442   typedef int BOOST_ASIO_UNUSED_TYPEDEF
443
444 #define BOOST_ASIO_WRITE_HANDLER_CHECK( \
445     handler_type, handler) \
446   typedef int BOOST_ASIO_UNUSED_TYPEDEF
447
448 #define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \
449     handler_type, handler) \
450   typedef int BOOST_ASIO_UNUSED_TYPEDEF
451
452 #define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
453     handler_type, handler) \
454   typedef int BOOST_ASIO_UNUSED_TYPEDEF
455
456 #define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
457     handler_type, handler, iter_type) \
458   typedef int BOOST_ASIO_UNUSED_TYPEDEF
459
460 #define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
461     handler_type, handler, iter_type) \
462   typedef int BOOST_ASIO_UNUSED_TYPEDEF
463
464 #define BOOST_ASIO_WAIT_HANDLER_CHECK( \
465     handler_type, handler) \
466   typedef int BOOST_ASIO_UNUSED_TYPEDEF
467
468 #define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \
469     handler_type, handler) \
470   typedef int BOOST_ASIO_UNUSED_TYPEDEF
471
472 #define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \
473     handler_type, handler) \
474   typedef int BOOST_ASIO_UNUSED_TYPEDEF
475
476 #define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \
477     handler_type, handler) \
478   typedef int BOOST_ASIO_UNUSED_TYPEDEF
479
480 #define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \
481     handler_type, handler) \
482   typedef int BOOST_ASIO_UNUSED_TYPEDEF
483
484 #endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
485
486 } // namespace detail
487 } // namespace asio
488 } // namespace boost
489
490 #endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP