1 | // Boost.Function library |
2 | |
3 | // Copyright Douglas Gregor 2001-2003. Use, modification and |
4 | // distribution is subject to the Boost Software License, Version |
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | // For more information, see http://www.boost.org |
9 | |
10 | #if defined(__clang__) && defined(__has_warning) |
11 | # if __has_warning( "-Wself-assign-overloaded" ) |
12 | # pragma clang diagnostic ignored "-Wself-assign-overloaded" |
13 | # endif |
14 | #endif |
15 | |
16 | #include <boost/function.hpp> |
17 | #include <boost/core/lightweight_test.hpp> |
18 | #include <functional> |
19 | #include <string> |
20 | #include <utility> |
21 | |
22 | #define BOOST_CHECK BOOST_TEST |
23 | |
24 | using boost::function; |
25 | using std::string; |
26 | |
27 | int global_int; |
28 | |
29 | struct write_five_obj { void operator()() const { global_int = 5; } }; |
30 | struct write_three_obj { int operator()() const { global_int = 3; return 7; }}; |
31 | static void write_five() { global_int = 5; } |
32 | static void write_three() { global_int = 3; } |
33 | struct generate_five_obj { int operator()() const { return 5; } }; |
34 | struct generate_three_obj { int operator()() const { return 3; } }; |
35 | static int generate_five() { return 5; } |
36 | static int generate_three() { return 3; } |
37 | static string identity_str(const string& s) { return s; } |
38 | static string string_cat(const string& s1, const string& s2) { return s1+s2; } |
39 | static int sum_ints(int x, int y) { return x+y; } |
40 | |
41 | struct write_const_1_nonconst_2 |
42 | { |
43 | void operator()() { global_int = 2; } |
44 | void operator()() const { global_int = 1; } |
45 | }; |
46 | |
47 | struct add_to_obj |
48 | { |
49 | add_to_obj(int v) : value(v) {} |
50 | |
51 | int operator()(int x) const { return value + x; } |
52 | |
53 | int value; |
54 | }; |
55 | |
56 | static void |
57 | test_zero_args() |
58 | { |
59 | typedef function<void ()> func_void_type; |
60 | |
61 | write_five_obj five; |
62 | write_three_obj three; |
63 | |
64 | // Default construction |
65 | func_void_type v1; |
66 | BOOST_CHECK(v1.empty()); |
67 | |
68 | // Assignment to an empty function |
69 | v1 = five; |
70 | BOOST_CHECK(v1 != 0); |
71 | |
72 | // Invocation of a function |
73 | global_int = 0; |
74 | v1(); |
75 | BOOST_CHECK(global_int == 5); |
76 | |
77 | // clear() method |
78 | v1.clear(); |
79 | BOOST_CHECK(v1 == 0); |
80 | |
81 | // Assignment to an empty function |
82 | v1 = three; |
83 | BOOST_CHECK(!v1.empty()); |
84 | |
85 | // Invocation and self-assignment |
86 | global_int = 0; |
87 | v1 = v1; |
88 | v1(); |
89 | BOOST_CHECK(global_int == 3); |
90 | |
91 | // Assignment to a non-empty function |
92 | v1 = five; |
93 | |
94 | // Invocation and self-assignment |
95 | global_int = 0; |
96 | v1 = (v1); |
97 | v1(); |
98 | BOOST_CHECK(global_int == 5); |
99 | |
100 | // clear |
101 | v1 = 0; |
102 | BOOST_CHECK(0 == v1); |
103 | |
104 | // Assignment to an empty function from a free function |
105 | v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five; |
106 | BOOST_CHECK(0 != v1); |
107 | |
108 | // Invocation |
109 | global_int = 0; |
110 | v1(); |
111 | BOOST_CHECK(global_int == 5); |
112 | |
113 | // Assignment to a non-empty function from a free function |
114 | v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three; |
115 | BOOST_CHECK(!v1.empty()); |
116 | |
117 | // Invocation |
118 | global_int = 0; |
119 | v1(); |
120 | BOOST_CHECK(global_int == 3); |
121 | |
122 | // Assignment |
123 | v1 = five; |
124 | BOOST_CHECK(!v1.empty()); |
125 | |
126 | // Invocation |
127 | global_int = 0; |
128 | v1(); |
129 | BOOST_CHECK(global_int == 5); |
130 | |
131 | // Assignment to a non-empty function from a free function |
132 | v1 = &write_three; |
133 | BOOST_CHECK(!v1.empty()); |
134 | |
135 | // Invocation |
136 | global_int = 0; |
137 | v1(); |
138 | BOOST_CHECK(global_int == 3); |
139 | |
140 | // Construction from another function (that is empty) |
141 | v1.clear(); |
142 | func_void_type v2(v1); |
143 | BOOST_CHECK(!v2? true : false); |
144 | |
145 | // Assignment to an empty function |
146 | v2 = three; |
147 | BOOST_CHECK(!v2.empty()); |
148 | |
149 | // Invocation |
150 | global_int = 0; |
151 | v2(); |
152 | BOOST_CHECK(global_int == 3); |
153 | |
154 | // Assignment to a non-empty function |
155 | v2 = (five); |
156 | |
157 | // Invocation |
158 | global_int = 0; |
159 | v2(); |
160 | BOOST_CHECK(global_int == 5); |
161 | |
162 | v2.clear(); |
163 | BOOST_CHECK(v2.empty()); |
164 | |
165 | // Assignment to an empty function from a free function |
166 | v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five); |
167 | BOOST_CHECK(v2? true : false); |
168 | |
169 | // Invocation |
170 | global_int = 0; |
171 | v2(); |
172 | BOOST_CHECK(global_int == 5); |
173 | |
174 | // Assignment to a non-empty function from a free function |
175 | v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three; |
176 | BOOST_CHECK(!v2.empty()); |
177 | |
178 | // Invocation |
179 | global_int = 0; |
180 | v2(); |
181 | BOOST_CHECK(global_int == 3); |
182 | |
183 | // Swapping |
184 | v1 = five; |
185 | swap(f1&: v1, f2&: v2); |
186 | v2(); |
187 | BOOST_CHECK(global_int == 5); |
188 | v1(); |
189 | BOOST_CHECK(global_int == 3); |
190 | swap(f1&: v1, f2&: v2); |
191 | v1.clear(); |
192 | |
193 | // Assignment |
194 | v2 = five; |
195 | BOOST_CHECK(!v2.empty()); |
196 | |
197 | // Invocation |
198 | global_int = 0; |
199 | v2(); |
200 | BOOST_CHECK(global_int == 5); |
201 | |
202 | // Assignment to a non-empty function from a free function |
203 | v2 = &write_three; |
204 | BOOST_CHECK(!v2.empty()); |
205 | |
206 | // Invocation |
207 | global_int = 0; |
208 | v2(); |
209 | BOOST_CHECK(global_int == 3); |
210 | |
211 | // Assignment to a function from an empty function |
212 | v2 = v1; |
213 | BOOST_CHECK(v2.empty()); |
214 | |
215 | // Assignment to a function from a function with a functor |
216 | v1 = three; |
217 | v2 = v1; |
218 | BOOST_CHECK(!v1.empty()); |
219 | BOOST_CHECK(!v2.empty()); |
220 | |
221 | // Invocation |
222 | global_int = 0; |
223 | v1(); |
224 | BOOST_CHECK(global_int == 3); |
225 | global_int = 0; |
226 | v2(); |
227 | BOOST_CHECK(global_int == 3); |
228 | |
229 | // Assign to a function from a function with a function |
230 | v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five; |
231 | v1 = v2; |
232 | BOOST_CHECK(!v1.empty()); |
233 | BOOST_CHECK(!v2.empty()); |
234 | global_int = 0; |
235 | v1(); |
236 | BOOST_CHECK(global_int == 5); |
237 | global_int = 0; |
238 | v2(); |
239 | BOOST_CHECK(global_int == 5); |
240 | |
241 | // Construct a function given another function containing a function |
242 | func_void_type v3(v1); |
243 | |
244 | // Invocation of a function |
245 | global_int = 0; |
246 | v3(); |
247 | BOOST_CHECK(global_int == 5); |
248 | |
249 | // clear() method |
250 | v3.clear(); |
251 | BOOST_CHECK(!v3? true : false); |
252 | |
253 | // Assignment to an empty function |
254 | v3 = three; |
255 | BOOST_CHECK(!v3.empty()); |
256 | |
257 | // Invocation |
258 | global_int = 0; |
259 | v3(); |
260 | BOOST_CHECK(global_int == 3); |
261 | |
262 | // Assignment to a non-empty function |
263 | v3 = five; |
264 | |
265 | // Invocation |
266 | global_int = 0; |
267 | v3(); |
268 | BOOST_CHECK(global_int == 5); |
269 | |
270 | // clear() |
271 | v3.clear(); |
272 | BOOST_CHECK(v3.empty()); |
273 | |
274 | // Assignment to an empty function from a free function |
275 | v3 = &write_five; |
276 | BOOST_CHECK(!v3.empty()); |
277 | |
278 | // Invocation |
279 | global_int = 0; |
280 | v3(); |
281 | BOOST_CHECK(global_int == 5); |
282 | |
283 | // Assignment to a non-empty function from a free function |
284 | v3 = &write_three; |
285 | BOOST_CHECK(!v3.empty()); |
286 | |
287 | // Invocation |
288 | global_int = 0; |
289 | v3(); |
290 | BOOST_CHECK(global_int == 3); |
291 | |
292 | // Assignment |
293 | v3 = five; |
294 | BOOST_CHECK(!v3.empty()); |
295 | |
296 | // Invocation |
297 | global_int = 0; |
298 | v3(); |
299 | BOOST_CHECK(global_int == 5); |
300 | |
301 | // Construction of a function from a function containing a functor |
302 | func_void_type v4(v3); |
303 | |
304 | // Invocation of a function |
305 | global_int = 0; |
306 | v4(); |
307 | BOOST_CHECK(global_int == 5); |
308 | |
309 | // clear() method |
310 | v4.clear(); |
311 | BOOST_CHECK(v4.empty()); |
312 | |
313 | // Assignment to an empty function |
314 | v4 = three; |
315 | BOOST_CHECK(!v4.empty()); |
316 | |
317 | // Invocation |
318 | global_int = 0; |
319 | v4(); |
320 | BOOST_CHECK(global_int == 3); |
321 | |
322 | // Assignment to a non-empty function |
323 | v4 = five; |
324 | |
325 | // Invocation |
326 | global_int = 0; |
327 | v4(); |
328 | BOOST_CHECK(global_int == 5); |
329 | |
330 | // clear() |
331 | v4.clear(); |
332 | BOOST_CHECK(v4.empty()); |
333 | |
334 | // Assignment to an empty function from a free function |
335 | v4 = &write_five; |
336 | BOOST_CHECK(!v4.empty()); |
337 | |
338 | // Invocation |
339 | global_int = 0; |
340 | v4(); |
341 | BOOST_CHECK(global_int == 5); |
342 | |
343 | // Assignment to a non-empty function from a free function |
344 | v4 = &write_three; |
345 | BOOST_CHECK(!v4.empty()); |
346 | |
347 | // Invocation |
348 | global_int = 0; |
349 | v4(); |
350 | BOOST_CHECK(global_int == 3); |
351 | |
352 | // Assignment |
353 | v4 = five; |
354 | BOOST_CHECK(!v4.empty()); |
355 | |
356 | // Invocation |
357 | global_int = 0; |
358 | v4(); |
359 | BOOST_CHECK(global_int == 5); |
360 | |
361 | // Construction of a function from a functor |
362 | func_void_type v5(five); |
363 | |
364 | // Invocation of a function |
365 | global_int = 0; |
366 | v5(); |
367 | BOOST_CHECK(global_int == 5); |
368 | |
369 | // clear() method |
370 | v5.clear(); |
371 | BOOST_CHECK(v5.empty()); |
372 | |
373 | // Assignment to an empty function |
374 | v5 = three; |
375 | BOOST_CHECK(!v5.empty()); |
376 | |
377 | // Invocation |
378 | global_int = 0; |
379 | v5(); |
380 | BOOST_CHECK(global_int == 3); |
381 | |
382 | // Assignment to a non-empty function |
383 | v5 = five; |
384 | |
385 | // Invocation |
386 | global_int = 0; |
387 | v5(); |
388 | BOOST_CHECK(global_int == 5); |
389 | |
390 | // clear() |
391 | v5.clear(); |
392 | BOOST_CHECK(v5.empty()); |
393 | |
394 | // Assignment to an empty function from a free function |
395 | v5 = &write_five; |
396 | BOOST_CHECK(!v5.empty()); |
397 | |
398 | // Invocation |
399 | global_int = 0; |
400 | v5(); |
401 | BOOST_CHECK(global_int == 5); |
402 | |
403 | // Assignment to a non-empty function from a free function |
404 | v5 = &write_three; |
405 | BOOST_CHECK(!v5.empty()); |
406 | |
407 | // Invocation |
408 | global_int = 0; |
409 | v5(); |
410 | BOOST_CHECK(global_int == 3); |
411 | |
412 | // Assignment |
413 | v5 = five; |
414 | BOOST_CHECK(!v5.empty()); |
415 | |
416 | // Invocation |
417 | global_int = 0; |
418 | v5(); |
419 | BOOST_CHECK(global_int == 5); |
420 | |
421 | // Construction of a function from a function |
422 | func_void_type v6(&write_five); |
423 | |
424 | // Invocation of a function |
425 | global_int = 0; |
426 | v6(); |
427 | BOOST_CHECK(global_int == 5); |
428 | |
429 | // clear() method |
430 | v6.clear(); |
431 | BOOST_CHECK(v6.empty()); |
432 | |
433 | // Assignment to an empty function |
434 | v6 = three; |
435 | BOOST_CHECK(!v6.empty()); |
436 | |
437 | // Invocation |
438 | global_int = 0; |
439 | v6(); |
440 | BOOST_CHECK(global_int == 3); |
441 | |
442 | // Assignment to a non-empty function |
443 | v6 = five; |
444 | |
445 | // Invocation |
446 | global_int = 0; |
447 | v6(); |
448 | BOOST_CHECK(global_int == 5); |
449 | |
450 | // clear() |
451 | v6.clear(); |
452 | BOOST_CHECK(v6.empty()); |
453 | |
454 | // Assignment to an empty function from a free function |
455 | v6 = &write_five; |
456 | BOOST_CHECK(!v6.empty()); |
457 | |
458 | // Invocation |
459 | global_int = 0; |
460 | v6(); |
461 | BOOST_CHECK(global_int == 5); |
462 | |
463 | // Assignment to a non-empty function from a free function |
464 | v6 = &write_three; |
465 | BOOST_CHECK(!v6.empty()); |
466 | |
467 | // Invocation |
468 | global_int = 0; |
469 | v6(); |
470 | BOOST_CHECK(global_int == 3); |
471 | |
472 | // Assignment |
473 | v6 = five; |
474 | BOOST_CHECK(!v6.empty()); |
475 | |
476 | // Invocation |
477 | global_int = 0; |
478 | v6(); |
479 | BOOST_CHECK(global_int == 5); |
480 | |
481 | // Const vs. non-const |
482 | write_const_1_nonconst_2 one_or_two; |
483 | const function<void ()> v7(one_or_two); |
484 | function<void ()> v8(one_or_two); |
485 | |
486 | global_int = 0; |
487 | v7(); |
488 | BOOST_CHECK(global_int == 2); |
489 | |
490 | global_int = 0; |
491 | v8(); |
492 | BOOST_CHECK(global_int == 2); |
493 | |
494 | // Test construction from 0 and comparison to 0 |
495 | func_void_type v9(0); |
496 | BOOST_CHECK(v9 == 0); |
497 | BOOST_CHECK(0 == v9); |
498 | |
499 | // Test return values |
500 | typedef function<int ()> func_int_type; |
501 | generate_five_obj gen_five; |
502 | generate_three_obj gen_three; |
503 | |
504 | func_int_type i0(gen_five); |
505 | |
506 | BOOST_CHECK(i0() == 5); |
507 | i0 = gen_three; |
508 | BOOST_CHECK(i0() == 3); |
509 | i0 = &generate_five; |
510 | BOOST_CHECK(i0() == 5); |
511 | i0 = &generate_three; |
512 | BOOST_CHECK(i0() == 3); |
513 | BOOST_CHECK(i0? true : false); |
514 | i0.clear(); |
515 | BOOST_CHECK(!i0? true : false); |
516 | |
517 | // Test return values with compatible types |
518 | typedef function<long ()> func_long_type; |
519 | func_long_type i1(gen_five); |
520 | |
521 | BOOST_CHECK(i1() == 5); |
522 | i1 = gen_three; |
523 | BOOST_CHECK(i1() == 3); |
524 | i1 = &generate_five; |
525 | BOOST_CHECK(i1() == 5); |
526 | i1 = &generate_three; |
527 | BOOST_CHECK(i1() == 3); |
528 | BOOST_CHECK(i1? true : false); |
529 | i1.clear(); |
530 | BOOST_CHECK(!i1? true : false); |
531 | } |
532 | |
533 | static void |
534 | test_one_arg() |
535 | { |
536 | std::negate<int> neg; |
537 | |
538 | function<int (int)> f1(neg); |
539 | BOOST_CHECK(f1(5) == -5); |
540 | |
541 | function<string (string)> id(&identity_str); |
542 | BOOST_CHECK(id("str" ) == "str" ); |
543 | |
544 | function<string (const char*)> id2(&identity_str); |
545 | BOOST_CHECK(id2("foo" ) == "foo" ); |
546 | |
547 | add_to_obj add_to(5); |
548 | function<int (int)> f2(add_to); |
549 | BOOST_CHECK(f2(3) == 8); |
550 | |
551 | const function<int (int)> cf2(add_to); |
552 | BOOST_CHECK(cf2(3) == 8); |
553 | } |
554 | |
555 | static void |
556 | test_two_args() |
557 | { |
558 | function<string (const string&, const string&)> cat(&string_cat); |
559 | BOOST_CHECK(cat("str" , "ing" ) == "string" ); |
560 | |
561 | function<int (short, short)> sum(&sum_ints); |
562 | BOOST_CHECK(sum(2, 3) == 5); |
563 | } |
564 | |
565 | static void |
566 | test_emptiness() |
567 | { |
568 | function<float ()> f1; |
569 | BOOST_CHECK(f1.empty()); |
570 | |
571 | function<float ()> f2; |
572 | f2 = f1; |
573 | BOOST_CHECK(f2.empty()); |
574 | |
575 | function<double ()> f3; |
576 | f3 = f2; |
577 | BOOST_CHECK(f3.empty()); |
578 | } |
579 | |
580 | struct X { |
581 | X(int v) : value(v) {} |
582 | |
583 | int twice() const { return 2*value; } |
584 | int plus(int v) { return value + v; } |
585 | |
586 | int value; |
587 | }; |
588 | |
589 | static void |
590 | test_member_functions() |
591 | { |
592 | boost::function<int (X*)> f1(&X::twice); |
593 | |
594 | X one(1); |
595 | X five(5); |
596 | |
597 | BOOST_CHECK(f1(&one) == 2); |
598 | BOOST_CHECK(f1(&five) == 10); |
599 | |
600 | boost::function<int (X*)> f1_2; |
601 | f1_2 = &X::twice; |
602 | |
603 | BOOST_CHECK(f1_2(&one) == 2); |
604 | BOOST_CHECK(f1_2(&five) == 10); |
605 | |
606 | boost::function<int (X&, int)> f2(&X::plus); |
607 | BOOST_CHECK(f2(one, 3) == 4); |
608 | BOOST_CHECK(f2(five, 4) == 9); |
609 | } |
610 | |
611 | struct add_with_throw_on_copy { |
612 | int operator()(int x, int y) const { return x+y; } |
613 | |
614 | add_with_throw_on_copy() {} |
615 | |
616 | add_with_throw_on_copy(const add_with_throw_on_copy&) |
617 | { |
618 | throw std::runtime_error("But this CAN'T throw" ); |
619 | } |
620 | |
621 | add_with_throw_on_copy& operator=(const add_with_throw_on_copy&) |
622 | { |
623 | throw std::runtime_error("But this CAN'T throw" ); |
624 | } |
625 | }; |
626 | |
627 | static void |
628 | test_ref() |
629 | { |
630 | add_with_throw_on_copy atc; |
631 | try { |
632 | boost::function<int (int, int)> f(boost::ref(t&: atc)); |
633 | BOOST_CHECK(f(1, 3) == 4); |
634 | } |
635 | catch(std::runtime_error const&) { |
636 | BOOST_ERROR("Nonthrowing constructor threw an exception" ); |
637 | } |
638 | } |
639 | |
640 | #if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700 |
641 | |
642 | // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311 |
643 | #pragma message("Skipping test_empty_ref on g++ 7 -std=c++17") |
644 | |
645 | static void test_empty_ref() |
646 | { |
647 | } |
648 | |
649 | #else |
650 | |
651 | static void dummy() {} |
652 | |
653 | static void test_empty_ref() |
654 | { |
655 | boost::function<void()> f1; |
656 | boost::function<void()> f2(boost::ref(t&: f1)); |
657 | |
658 | try { |
659 | f2(); |
660 | BOOST_ERROR("Exception didn't throw for reference to empty function." ); |
661 | } |
662 | catch(std::runtime_error const&) {} |
663 | |
664 | f1 = dummy; |
665 | |
666 | try { |
667 | f2(); |
668 | } |
669 | catch(std::runtime_error const&) { |
670 | BOOST_ERROR("Error calling referenced function." ); |
671 | } |
672 | } |
673 | |
674 | #endif |
675 | |
676 | |
677 | static void test_exception() |
678 | { |
679 | boost::function<int (int, int)> f; |
680 | try { |
681 | f(5, 4); |
682 | BOOST_CHECK(false); |
683 | } |
684 | catch(boost::bad_function_call const&) { |
685 | // okay |
686 | } |
687 | } |
688 | |
689 | typedef boost::function< void * (void * reader) > reader_type; |
690 | typedef std::pair<int, reader_type> mapped_type; |
691 | |
692 | static void test_implicit() |
693 | { |
694 | mapped_type m; |
695 | m = mapped_type(); |
696 | } |
697 | |
698 | static void test_call_obj(boost::function<int (int, int)> f) |
699 | { |
700 | BOOST_CHECK(!f.empty()); |
701 | } |
702 | |
703 | static void test_call_cref(const boost::function<int (int, int)>& f) |
704 | { |
705 | BOOST_CHECK(!f.empty()); |
706 | } |
707 | |
708 | static void test_call() |
709 | { |
710 | test_call_obj(f: std::plus<int>()); |
711 | test_call_cref(f: std::plus<int>()); |
712 | } |
713 | |
714 | struct big_aggregating_structure { |
715 | int disable_small_objects_optimizations[32]; |
716 | |
717 | big_aggregating_structure() |
718 | { |
719 | ++ global_int; |
720 | } |
721 | |
722 | big_aggregating_structure(const big_aggregating_structure&) |
723 | { |
724 | ++ global_int; |
725 | } |
726 | |
727 | ~big_aggregating_structure() |
728 | { |
729 | -- global_int; |
730 | } |
731 | |
732 | void operator()() |
733 | { |
734 | ++ global_int; |
735 | } |
736 | |
737 | void operator()(int) |
738 | { |
739 | ++ global_int; |
740 | } |
741 | }; |
742 | |
743 | template <class FunctionT> |
744 | static void test_move_semantics() |
745 | { |
746 | typedef FunctionT f1_type; |
747 | |
748 | big_aggregating_structure obj; |
749 | |
750 | f1_type f1 = obj; |
751 | global_int = 0; |
752 | f1(); |
753 | |
754 | BOOST_CHECK(!f1.empty()); |
755 | BOOST_CHECK(global_int == 1); |
756 | |
757 | // Testing rvalue constructors |
758 | f1_type f2(static_cast<f1_type&&>(f1)); |
759 | BOOST_CHECK(f1.empty()); |
760 | BOOST_CHECK(!f2.empty()); |
761 | BOOST_CHECK(global_int == 1); |
762 | f2(); |
763 | BOOST_CHECK(global_int == 2); |
764 | |
765 | f1_type f3(static_cast<f1_type&&>(f2)); |
766 | BOOST_CHECK(f1.empty()); |
767 | BOOST_CHECK(f2.empty()); |
768 | BOOST_CHECK(!f3.empty()); |
769 | BOOST_CHECK(global_int == 2); |
770 | f3(); |
771 | BOOST_CHECK(global_int == 3); |
772 | |
773 | // Testing move assignment |
774 | f1_type f4; |
775 | BOOST_CHECK(f4.empty()); |
776 | f4 = static_cast<f1_type&&>(f3); |
777 | BOOST_CHECK(f1.empty()); |
778 | BOOST_CHECK(f2.empty()); |
779 | BOOST_CHECK(f3.empty()); |
780 | BOOST_CHECK(!f4.empty()); |
781 | BOOST_CHECK(global_int == 3); |
782 | f4(); |
783 | BOOST_CHECK(global_int == 4); |
784 | |
785 | // Testing self move assignment |
786 | f4 = static_cast<f1_type&&>(f4); |
787 | BOOST_CHECK(!f4.empty()); |
788 | BOOST_CHECK(global_int == 4); |
789 | |
790 | // Testing, that no memory leaked when assigning to nonempty function |
791 | f4 = obj; |
792 | BOOST_CHECK(!f4.empty()); |
793 | BOOST_CHECK(global_int == 4); |
794 | f1_type f5 = obj; |
795 | BOOST_CHECK(global_int == 5); |
796 | f4 = static_cast<f1_type&&>(f5); |
797 | BOOST_CHECK(global_int == 4); |
798 | } |
799 | |
800 | int main() |
801 | { |
802 | test_zero_args(); |
803 | test_one_arg(); |
804 | test_two_args(); |
805 | test_emptiness(); |
806 | test_member_functions(); |
807 | test_ref(); |
808 | test_empty_ref(); |
809 | test_exception(); |
810 | test_implicit(); |
811 | test_call(); |
812 | test_move_semantics<function<void()> >(); |
813 | test_move_semantics<boost::function0<void> >(); |
814 | |
815 | return boost::report_errors(); |
816 | } |
817 | |