1 //
2 // connect.cpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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 // Disable autolinking for unit tests.
12 #if !defined(BOOST_ALL_NO_LIB)
13 #define BOOST_ALL_NO_LIB 1
14 #endif // !defined(BOOST_ALL_NO_LIB)
15
16 // Test that header file is self-contained.
17 #include <boost/asio/execution/connect.hpp>
18
19 #include <boost/system/error_code.hpp>
20 #include "../unit_test.hpp"
21
22 namespace exec = boost::asio::execution;
23
24 static int call_count = 0;
25
26 struct operation_state
27 {
startoperation_state28 void start() BOOST_ASIO_NOEXCEPT
29 {
30 }
31 };
32
33 namespace boost {
34 namespace asio {
35 namespace traits {
36
37 #if !defined(BOOST_ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)
38
39 template <>
40 struct start_member<operation_state>
41 {
42 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
43 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
44 typedef void result_type;
45 };
46
47 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)
48
49 } // namespace traits
50 } // namespace asio
51 } // namespace boost
52
53 struct no_connect_1
54 {
55 };
56
57 struct no_connect_2 : exec::sender_base
58 {
59 };
60
61 struct no_connect_3
62 {
63 template <typename R>
connectno_connect_364 operation_state connect(BOOST_ASIO_MOVE_ARG(R) r)
65 {
66 (void)r;
67 return operation_state();
68 }
69 };
70
71 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
72
73 namespace boost {
74 namespace asio {
75 namespace traits {
76
77 template <typename R>
78 struct connect_member<no_connect_3, R>
79 {
80 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
81 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
82 typedef operation_state result_type;
83 };
84
85 } // namespace traits
86 } // namespace asio
87 } // namespace boost
88
89 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
90
91 struct const_member_connect : exec::sender_base
92 {
const_member_connectconst_member_connect93 const_member_connect()
94 {
95 }
96
97 template <typename R>
connectconst_member_connect98 operation_state connect(BOOST_ASIO_MOVE_ARG(R) r) const
99 {
100 (void)r;
101 ++call_count;
102 return operation_state();
103 }
104 };
105
106 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
107
108 namespace boost {
109 namespace asio {
110 namespace traits {
111
112 template <typename R>
113 struct connect_member<const const_member_connect, R>
114 {
115 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
116 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
117 typedef operation_state result_type;
118 };
119
120 } // namespace traits
121 } // namespace asio
122 } // namespace boost
123
124 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
125
126 struct free_connect_const_receiver : exec::sender_base
127 {
free_connect_const_receiverfree_connect_const_receiver128 free_connect_const_receiver()
129 {
130 }
131
132 template <typename R>
connect(const free_connect_const_receiver &,BOOST_ASIO_MOVE_ARG (R)r)133 friend operation_state connect(
134 const free_connect_const_receiver&, BOOST_ASIO_MOVE_ARG(R) r)
135 {
136 (void)r;
137 ++call_count;
138 return operation_state();
139 }
140 };
141
142 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)
143
144 namespace boost {
145 namespace asio {
146 namespace traits {
147
148 template <typename R>
149 struct connect_free<const free_connect_const_receiver, R>
150 {
151 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
152 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
153 typedef operation_state result_type;
154 };
155
156 } // namespace traits
157 } // namespace asio
158 } // namespace boost
159
160 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)
161
162 struct non_const_member_connect : exec::sender_base
163 {
164 template <typename R>
connectnon_const_member_connect165 operation_state connect(BOOST_ASIO_MOVE_ARG(R) r)
166 {
167 (void)r;
168 ++call_count;
169 return operation_state();
170 }
171 };
172
173 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
174
175 namespace boost {
176 namespace asio {
177 namespace traits {
178
179 template <typename R>
180 struct connect_member<non_const_member_connect, R>
181 {
182 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
183 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
184 typedef operation_state result_type;
185 };
186
187 } // namespace traits
188 } // namespace asio
189 } // namespace boost
190
191 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)
192
193 struct free_connect_non_const_receiver : exec::sender_base
194 {
free_connect_non_const_receiverfree_connect_non_const_receiver195 free_connect_non_const_receiver()
196 {
197 }
198
199 template <typename R>
connect(free_connect_non_const_receiver &,BOOST_ASIO_MOVE_ARG (R)r)200 friend operation_state connect(
201 free_connect_non_const_receiver&, BOOST_ASIO_MOVE_ARG(R) r)
202 {
203 (void)r;
204 ++call_count;
205 return operation_state();
206 }
207 };
208
209 #if !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)
210
211 namespace boost {
212 namespace asio {
213 namespace traits {
214
215 template <typename R>
216 struct connect_free<free_connect_non_const_receiver, R>
217 {
218 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
219 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
220 typedef operation_state result_type;
221 };
222
223 } // namespace traits
224 } // namespace asio
225 } // namespace boost
226
227 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)
228
229 struct receiver
230 {
receiverreceiver231 receiver()
232 {
233 }
234
receiverreceiver235 receiver(const receiver&)
236 {
237 }
238
239 #if defined(BOOST_ASIO_HAS_MOVE)
receiverreceiver240 receiver(receiver&&) BOOST_ASIO_NOEXCEPT
241 {
242 }
243 #endif // defined(BOOST_ASIO_HAS_MOVE)
244
245 template <typename E>
set_errorreceiver246 void set_error(BOOST_ASIO_MOVE_ARG(E) e) BOOST_ASIO_NOEXCEPT
247 {
248 (void)e;
249 }
250
set_donereceiver251 void set_done() BOOST_ASIO_NOEXCEPT
252 {
253 }
254 };
255
256 namespace boost {
257 namespace asio {
258 namespace traits {
259
260 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
261
262 template <typename E>
263 struct set_error_member<receiver, E>
264 {
265 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
266 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
267 typedef void result_type;
268 };
269
270 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
271 #if !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
272
273 template <>
274 struct set_done_member<receiver>
275 {
276 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
277 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
278 typedef void result_type;
279 };
280
281 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)
282
283 } // namespace traits
284 } // namespace asio
285 } // namespace boost
286
287 struct executor
288 {
executorexecutor289 executor()
290 {
291 }
292
executorexecutor293 executor(const executor&) BOOST_ASIO_NOEXCEPT
294 {
295 }
296
297 #if defined(BOOST_ASIO_HAS_MOVE)
executorexecutor298 executor(executor&&) BOOST_ASIO_NOEXCEPT
299 {
300 }
301 #endif // defined(BOOST_ASIO_HAS_MOVE)
302
303 template <typename F>
executeexecutor304 void execute(BOOST_ASIO_MOVE_ARG(F) f) const BOOST_ASIO_NOEXCEPT
305 {
306 (void)f;
307 }
308
operator ==executor309 bool operator==(const executor&) const BOOST_ASIO_NOEXCEPT
310 {
311 return true;
312 }
313
operator !=executor314 bool operator!=(const executor&) const BOOST_ASIO_NOEXCEPT
315 {
316 return false;
317 }
318 };
319
320 namespace boost {
321 namespace asio {
322 namespace traits {
323
324 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
325
326 template <typename F>
327 struct execute_member<executor, F>
328 {
329 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
330 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
331 typedef void result_type;
332 };
333
334 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)
335 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
336
337 template <>
338 struct equality_comparable<executor>
339 {
340 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
341 BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
342 };
343
344 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
345
346 } // namespace traits
347 } // namespace asio
348 } // namespace boost
349
test_can_connect()350 void test_can_connect()
351 {
352 BOOST_ASIO_CONSTEXPR bool b1 = exec::can_connect<
353 no_connect_1&, receiver>::value;
354 BOOST_ASIO_CHECK(b1 == false);
355
356 BOOST_ASIO_CONSTEXPR bool b2 = exec::can_connect<
357 const no_connect_1&, receiver>::value;
358 BOOST_ASIO_CHECK(b2 == false);
359
360 BOOST_ASIO_CONSTEXPR bool b3 = exec::can_connect<
361 no_connect_2&, receiver>::value;
362 BOOST_ASIO_CHECK(b3 == false);
363
364 BOOST_ASIO_CONSTEXPR bool b4 = exec::can_connect<
365 const no_connect_2&, receiver>::value;
366 BOOST_ASIO_CHECK(b4 == false);
367
368 BOOST_ASIO_CONSTEXPR bool b5 = exec::can_connect<
369 no_connect_3&, receiver>::value;
370 BOOST_ASIO_CHECK(b5 == false);
371
372 BOOST_ASIO_CONSTEXPR bool b6 = exec::can_connect<
373 const no_connect_3&, receiver>::value;
374 BOOST_ASIO_CHECK(b6 == false);
375
376 BOOST_ASIO_CONSTEXPR bool b7 = exec::can_connect<
377 const_member_connect&, receiver>::value;
378 BOOST_ASIO_CHECK(b7 == true);
379
380 BOOST_ASIO_CONSTEXPR bool b8 = exec::can_connect<
381 const const_member_connect&, receiver>::value;
382 BOOST_ASIO_CHECK(b8 == true);
383
384 BOOST_ASIO_CONSTEXPR bool b9 = exec::can_connect<
385 free_connect_const_receiver&, receiver>::value;
386 BOOST_ASIO_CHECK(b9 == true);
387
388 BOOST_ASIO_CONSTEXPR bool b10 = exec::can_connect<
389 const free_connect_const_receiver&, receiver>::value;
390 BOOST_ASIO_CHECK(b10 == true);
391
392 BOOST_ASIO_CONSTEXPR bool b11 = exec::can_connect<
393 non_const_member_connect&, receiver>::value;
394 BOOST_ASIO_CHECK(b11 == true);
395
396 BOOST_ASIO_CONSTEXPR bool b12 = exec::can_connect<
397 const non_const_member_connect&, receiver>::value;
398 BOOST_ASIO_CHECK(b12 == false);
399
400 BOOST_ASIO_CONSTEXPR bool b13 = exec::can_connect<
401 free_connect_non_const_receiver&, receiver>::value;
402 BOOST_ASIO_CHECK(b13 == true);
403
404 BOOST_ASIO_CONSTEXPR bool b14 = exec::can_connect<
405 const free_connect_non_const_receiver&, receiver>::value;
406 BOOST_ASIO_CHECK(b14 == false);
407
408 BOOST_ASIO_CONSTEXPR bool b15 = exec::can_connect<
409 executor&, receiver>::value;
410 BOOST_ASIO_CHECK(b15 == true);
411
412 BOOST_ASIO_CONSTEXPR bool b16 = exec::can_connect<
413 const executor&, receiver>::value;
414 BOOST_ASIO_CHECK(b16 == true);
415 }
416
increment(int * count)417 void increment(int* count)
418 {
419 ++(*count);
420 }
421
test_connect()422 void test_connect()
423 {
424 receiver r;
425
426 call_count = 0;
427 const_member_connect s1;
428 operation_state o1 = exec::connect(s1, r);
429 BOOST_ASIO_CHECK(call_count == 1);
430 (void)o1;
431
432 call_count = 0;
433 const const_member_connect s2;
434 operation_state o2 = exec::connect(s2, r);
435 BOOST_ASIO_CHECK(call_count == 1);
436 (void)o2;
437
438 call_count = 0;
439 operation_state o3 = exec::connect(const_member_connect(), r);
440 BOOST_ASIO_CHECK(call_count == 1);
441 (void)o3;
442
443 call_count = 0;
444 free_connect_const_receiver s3;
445 operation_state o4 = exec::connect(s3, r);
446 BOOST_ASIO_CHECK(call_count == 1);
447 (void)o4;
448
449 call_count = 0;
450 const free_connect_const_receiver s4;
451 operation_state o5 = exec::connect(s4, r);
452 BOOST_ASIO_CHECK(call_count == 1);
453 (void)o5;
454
455 call_count = 0;
456 operation_state o6 = exec::connect(free_connect_const_receiver(), r);
457 BOOST_ASIO_CHECK(call_count == 1);
458 (void)o6;
459
460 call_count = 0;
461 non_const_member_connect s5;
462 operation_state o7 = exec::connect(s5, r);
463 BOOST_ASIO_CHECK(call_count == 1);
464 (void)o7;
465
466 call_count = 0;
467 free_connect_non_const_receiver s6;
468 operation_state o8 = exec::connect(s6, r);
469 BOOST_ASIO_CHECK(call_count == 1);
470 (void)o8;
471
472 executor s7;
473 exec::connect_result<executor&,
474 receiver&>::type o9 = exec::connect(s7, r);
475 BOOST_ASIO_CHECK((
476 exec::is_operation_state<
477 exec::connect_result<executor&, receiver&>::type
478 >::value));
479 (void)o9;
480
481 const executor s8;
482 exec::connect_result<const executor&,
483 receiver&>::type o10 = exec::connect(s8, r);
484 (void)exec::connect(s8, r);
485 BOOST_ASIO_CHECK((
486 exec::is_operation_state<
487 exec::connect_result<const executor&, receiver&>::type
488 >::value));
489 (void)o10;
490 }
491
492 BOOST_ASIO_TEST_SUITE
493 (
494 "connect",
495 BOOST_ASIO_TEST_CASE(test_can_connect)
496 BOOST_ASIO_TEST_CASE(test_connect)
497 )
498