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 <cassert>
20#include <string>
21
22#define BOOST_CHECK BOOST_TEST
23
24using namespace boost;
25using std::string;
26using std::negate;
27
28int global_int;
29
30struct write_five_obj { void operator()() const { global_int = 5; } };
31struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
32static void write_five() { global_int = 5; }
33static void write_three() { global_int = 3; }
34struct generate_five_obj { int operator()() const { return 5; } };
35struct generate_three_obj { int operator()() const { return 3; } };
36static int generate_five() { return 5; }
37static int generate_three() { return 3; }
38static string identity_str(const string& s) { return s; }
39static string string_cat(const string& s1, const string& s2) { return s1+s2; }
40static int sum_ints(int x, int y) { return x+y; }
41
42struct write_const_1_nonconst_2
43{
44 void operator()() { global_int = 2; }
45 void operator()() const { global_int = 1; }
46};
47
48struct add_to_obj
49{
50 add_to_obj(int v) : value(v) {}
51
52 int operator()(int x) const { return value + x; }
53
54 int value;
55};
56
57static void
58test_zero_args()
59{
60 typedef function0<void> func_void_type;
61
62 write_five_obj five = write_five_obj(); // Initialization for Borland C++ 5.5
63 write_three_obj three = write_three_obj(); // Ditto
64
65 // Default construction
66 func_void_type v1;
67 BOOST_CHECK(v1.empty());
68
69 // Assignment to an empty function
70 v1 = five;
71 BOOST_CHECK(!v1.empty());
72
73 // Invocation of a function
74 global_int = 0;
75 v1();
76 BOOST_CHECK(global_int == 5);
77
78 // clear() method
79 v1.clear();
80 BOOST_CHECK(!v1);
81
82 // Assignment to an empty function
83 v1 = three;
84 BOOST_CHECK(!v1.empty());
85
86 // Invocation and self-assignment
87 global_int = 0;
88 v1 = v1;
89 v1();
90 BOOST_CHECK(global_int == 3);
91
92 // Assignment to a non-empty function
93 v1 = five;
94
95 // Invocation and self-assignment
96 global_int = 0;
97 v1 = (v1);
98 v1();
99 BOOST_CHECK(global_int == 5);
100
101 // clear
102 v1 = 0;
103 BOOST_CHECK(v1.empty());
104
105 // Assignment to an empty function from a free function
106 v1 = &write_five;
107 BOOST_CHECK(!v1.empty());
108
109 // Invocation
110 global_int = 0;
111 v1();
112 BOOST_CHECK(global_int == 5);
113
114 // Assignment to a non-empty function from a free function
115 v1 = &write_three;
116 BOOST_CHECK(!v1.empty());
117
118 // Invocation
119 global_int = 0;
120 v1();
121 BOOST_CHECK(global_int == 3);
122
123 // Assignment
124 v1 = five;
125 BOOST_CHECK(!v1.empty());
126
127 // Invocation
128 global_int = 0;
129 v1();
130 BOOST_CHECK(global_int == 5);
131
132 // Assignment to a non-empty function from a free function
133 v1 = write_three;
134 BOOST_CHECK(!v1.empty());
135
136 // Invocation
137 global_int = 0;
138 v1();
139 BOOST_CHECK(global_int == 3);
140
141 // Construction from another function (that is empty)
142 v1.clear();
143 func_void_type v2(v1);
144 BOOST_CHECK(!v2? true : false);
145
146 // Assignment to an empty function
147 v2 = three;
148 BOOST_CHECK(!v2.empty());
149
150 // Invocation
151 global_int = 0;
152 v2();
153 BOOST_CHECK(global_int == 3);
154
155 // Assignment to a non-empty function
156 v2 = (five);
157
158 // Invocation
159 global_int = 0;
160 v2();
161 BOOST_CHECK(global_int == 5);
162
163 v2.clear();
164 BOOST_CHECK(v2.empty());
165
166 // Assignment to an empty function from a free function
167 v2 = (&write_five);
168 BOOST_CHECK(v2? true : false);
169
170 // Invocation
171 global_int = 0;
172 v2();
173 BOOST_CHECK(global_int == 5);
174
175 // Assignment to a non-empty function from a free function
176 v2 = &write_three;
177 BOOST_CHECK(!v2.empty());
178
179 // Invocation
180 global_int = 0;
181 v2();
182 BOOST_CHECK(global_int == 3);
183
184 // Swapping
185 v1 = five;
186 swap(f1&: v1, f2&: v2);
187 v2();
188 BOOST_CHECK(global_int == 5);
189 v1();
190 BOOST_CHECK(global_int == 3);
191 swap(f1&: v1, f2&: v2);
192 v1.clear();
193
194 // Assignment
195 v2 = five;
196 BOOST_CHECK(!v2.empty());
197
198 // Invocation
199 global_int = 0;
200 v2();
201 BOOST_CHECK(global_int == 5);
202
203 // Assignment to a non-empty function from a free function
204 v2 = &write_three;
205 BOOST_CHECK(!v2.empty());
206
207 // Invocation
208 global_int = 0;
209 v2();
210 BOOST_CHECK(global_int == 3);
211
212 // Assignment to a function from an empty function
213 v2 = v1;
214 BOOST_CHECK(v2.empty());
215
216 // Assignment to a function from a function with a functor
217 v1 = three;
218 v2 = v1;
219 BOOST_CHECK(!v1.empty());
220 BOOST_CHECK(!v2.empty());
221
222 // Invocation
223 global_int = 0;
224 v1();
225 BOOST_CHECK(global_int == 3);
226 global_int = 0;
227 v2();
228 BOOST_CHECK(global_int == 3);
229
230 // Assign to a function from a function with a function
231 v2 = &write_five;
232 v1 = v2;
233 BOOST_CHECK(!v1.empty());
234 BOOST_CHECK(!v2.empty());
235 global_int = 0;
236 v1();
237 BOOST_CHECK(global_int == 5);
238 global_int = 0;
239 v2();
240 BOOST_CHECK(global_int == 5);
241
242 // Construct a function given another function containing a function
243 func_void_type v3(v1);
244
245 // Invocation of a function
246 global_int = 0;
247 v3();
248 BOOST_CHECK(global_int == 5);
249
250 // clear() method
251 v3.clear();
252 BOOST_CHECK(!v3? true : false);
253
254 // Assignment to an empty function
255 v3 = three;
256 BOOST_CHECK(!v3.empty());
257
258 // Invocation
259 global_int = 0;
260 v3();
261 BOOST_CHECK(global_int == 3);
262
263 // Assignment to a non-empty function
264 v3 = five;
265
266 // Invocation
267 global_int = 0;
268 v3();
269 BOOST_CHECK(global_int == 5);
270
271 // clear()
272 v3.clear();
273 BOOST_CHECK(v3.empty());
274
275 // Assignment to an empty function from a free function
276 v3 = &write_five;
277 BOOST_CHECK(!v3.empty());
278
279 // Invocation
280 global_int = 0;
281 v3();
282 BOOST_CHECK(global_int == 5);
283
284 // Assignment to a non-empty function from a free function
285 v3 = &write_three;
286 BOOST_CHECK(!v3.empty());
287
288 // Invocation
289 global_int = 0;
290 v3();
291 BOOST_CHECK(global_int == 3);
292
293 // Assignment
294 v3 = five;
295 BOOST_CHECK(!v3.empty());
296
297 // Invocation
298 global_int = 0;
299 v3();
300 BOOST_CHECK(global_int == 5);
301
302 // Construction of a function from a function containing a functor
303 func_void_type v4(v3);
304
305 // Invocation of a function
306 global_int = 0;
307 v4();
308 BOOST_CHECK(global_int == 5);
309
310 // clear() method
311 v4.clear();
312 BOOST_CHECK(v4.empty());
313
314 // Assignment to an empty function
315 v4 = three;
316 BOOST_CHECK(!v4.empty());
317
318 // Invocation
319 global_int = 0;
320 v4();
321 BOOST_CHECK(global_int == 3);
322
323 // Assignment to a non-empty function
324 v4 = five;
325
326 // Invocation
327 global_int = 0;
328 v4();
329 BOOST_CHECK(global_int == 5);
330
331 // clear()
332 v4.clear();
333 BOOST_CHECK(v4.empty());
334
335 // Assignment to an empty function from a free function
336 v4 = &write_five;
337 BOOST_CHECK(!v4.empty());
338
339 // Invocation
340 global_int = 0;
341 v4();
342 BOOST_CHECK(global_int == 5);
343
344 // Assignment to a non-empty function from a free function
345 v4 = &write_three;
346 BOOST_CHECK(!v4.empty());
347
348 // Invocation
349 global_int = 0;
350 v4();
351 BOOST_CHECK(global_int == 3);
352
353 // Assignment
354 v4 = five;
355 BOOST_CHECK(!v4.empty());
356
357 // Invocation
358 global_int = 0;
359 v4();
360 BOOST_CHECK(global_int == 5);
361
362 // Construction of a function from a functor
363 func_void_type v5(five);
364
365 // Invocation of a function
366 global_int = 0;
367 v5();
368 BOOST_CHECK(global_int == 5);
369
370 // clear() method
371 v5.clear();
372 BOOST_CHECK(v5.empty());
373
374 // Assignment to an empty function
375 v5 = three;
376 BOOST_CHECK(!v5.empty());
377
378 // Invocation
379 global_int = 0;
380 v5();
381 BOOST_CHECK(global_int == 3);
382
383 // Assignment to a non-empty function
384 v5 = five;
385
386 // Invocation
387 global_int = 0;
388 v5();
389 BOOST_CHECK(global_int == 5);
390
391 // clear()
392 v5.clear();
393 BOOST_CHECK(v5.empty());
394
395 // Assignment to an empty function from a free function
396 v5 = &write_five;
397 BOOST_CHECK(!v5.empty());
398
399 // Invocation
400 global_int = 0;
401 v5();
402 BOOST_CHECK(global_int == 5);
403
404 // Assignment to a non-empty function from a free function
405 v5 = &write_three;
406 BOOST_CHECK(!v5.empty());
407
408 // Invocation
409 global_int = 0;
410 v5();
411 BOOST_CHECK(global_int == 3);
412
413 // Assignment
414 v5 = five;
415 BOOST_CHECK(!v5.empty());
416
417 // Invocation
418 global_int = 0;
419 v5();
420 BOOST_CHECK(global_int == 5);
421
422 // Construction of a function from a function
423 func_void_type v6(&write_five);
424
425 // Invocation of a function
426 global_int = 0;
427 v6();
428 BOOST_CHECK(global_int == 5);
429
430 // clear() method
431 v6.clear();
432 BOOST_CHECK(v6.empty());
433
434 // Assignment to an empty function
435 v6 = three;
436 BOOST_CHECK(!v6.empty());
437
438 // Invocation
439 global_int = 0;
440 v6();
441 BOOST_CHECK(global_int == 3);
442
443 // Assignment to a non-empty function
444 v6 = five;
445
446 // Invocation
447 global_int = 0;
448 v6();
449 BOOST_CHECK(global_int == 5);
450
451 // clear()
452 v6.clear();
453 BOOST_CHECK(v6.empty());
454
455 // Assignment to an empty function from a free function
456 v6 = &write_five;
457 BOOST_CHECK(!v6.empty());
458
459 // Invocation
460 global_int = 0;
461 v6();
462 BOOST_CHECK(global_int == 5);
463
464 // Assignment to a non-empty function from a free function
465 v6 = &write_three;
466 BOOST_CHECK(!v6.empty());
467
468 // Invocation
469 global_int = 0;
470 v6();
471 BOOST_CHECK(global_int == 3);
472
473 // Assignment
474 v6 = five;
475 BOOST_CHECK(!v6.empty());
476
477 // Invocation
478 global_int = 0;
479 v6();
480 BOOST_CHECK(global_int == 5);
481
482 // Const vs. non-const
483 // Initialization for Borland C++ 5.5
484 write_const_1_nonconst_2 one_or_two = write_const_1_nonconst_2();
485 const function0<void> v7(one_or_two);
486 function0<void> v8(one_or_two);
487
488 global_int = 0;
489 v7();
490 BOOST_CHECK(global_int == 2);
491
492 global_int = 0;
493 v8();
494 BOOST_CHECK(global_int == 2);
495
496 // Test construction from 0 and comparison to 0
497 func_void_type v9(0);
498 BOOST_CHECK(v9 == 0);
499# if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG)
500 BOOST_CHECK(0 == v9);
501#else
502 BOOST_CHECK(v9.empty());
503#endif
504
505 // Test return values
506 typedef function0<int> func_int_type;
507 // Initialization for Borland C++ 5.5
508 generate_five_obj gen_five = generate_five_obj();
509 generate_three_obj gen_three = generate_three_obj();
510 func_int_type i0(gen_five);
511
512 BOOST_CHECK(i0() == 5);
513 i0 = gen_three;
514 BOOST_CHECK(i0() == 3);
515 i0 = &generate_five;
516 BOOST_CHECK(i0() == 5);
517 i0 = &generate_three;
518 BOOST_CHECK(i0() == 3);
519 BOOST_CHECK(i0? true : false);
520 i0.clear();
521 BOOST_CHECK(!i0? true : false);
522
523 // Test return values with compatible types
524 typedef function0<long> func_long_type;
525 func_long_type i1(gen_five);
526
527 BOOST_CHECK(i1() == 5);
528 i1 = gen_three;
529 BOOST_CHECK(i1() == 3);
530 i1 = &generate_five;
531 BOOST_CHECK(i1() == 5);
532 i1 = &generate_three;
533 BOOST_CHECK(i1() == 3);
534 BOOST_CHECK(i1? true : false);
535 i1.clear();
536 BOOST_CHECK(!i1? true : false);
537}
538
539static void
540test_one_arg()
541{
542 negate<int> neg = negate<int>(); // Initialization for Borland C++ 5.5
543
544 function1<int, int> f1(neg);
545 BOOST_CHECK(f1(5) == -5);
546
547 function1<string, string> id(&identity_str);
548 BOOST_CHECK(id("str") == "str");
549
550 function1<std::string, const char*> id2(&identity_str);
551 BOOST_CHECK(id2("foo") == "foo");
552
553 add_to_obj add_to(5);
554 function1<int, int> f2(add_to);
555 BOOST_CHECK(f2(3) == 8);
556
557 const function1<int, int> cf2(add_to);
558 BOOST_CHECK(cf2(3) == 8);
559}
560
561static void
562test_two_args()
563{
564 function2<string, const string&, const string&> cat(&string_cat);
565 BOOST_CHECK(cat("str", "ing") == "string");
566
567 function2<int, short, short> sum(&sum_ints);
568 BOOST_CHECK(sum(2, 3) == 5);
569}
570
571static void
572test_emptiness()
573{
574 function0<float> f1;
575 BOOST_CHECK(f1.empty());
576
577 function0<float> f2;
578 f2 = f1;
579 BOOST_CHECK(f2.empty());
580
581 function0<double> f3;
582 f3 = f2;
583 BOOST_CHECK(f3.empty());
584}
585
586struct X {
587 X(int v) : value(v) {}
588
589 int twice() const { return 2*value; }
590 int plus(int v) { return value + v; }
591
592 int value;
593};
594
595static void
596test_member_functions()
597{
598
599 boost::function1<int, X*> f1(&X::twice);
600
601 X one(1);
602 X five(5);
603
604 BOOST_CHECK(f1(&one) == 2);
605 BOOST_CHECK(f1(&five) == 10);
606
607 boost::function1<int, X*> f1_2;
608 f1_2 = &X::twice;
609
610 BOOST_CHECK(f1_2(&one) == 2);
611 BOOST_CHECK(f1_2(&five) == 10);
612
613 boost::function2<int, X&, int> f2(&X::plus);
614 BOOST_CHECK(f2(one, 3) == 4);
615 BOOST_CHECK(f2(five, 4) == 9);
616}
617
618struct add_with_throw_on_copy {
619 int operator()(int x, int y) const { return x+y; }
620
621 add_with_throw_on_copy() {}
622
623 add_with_throw_on_copy(const add_with_throw_on_copy&)
624 {
625 throw std::runtime_error("But this CAN'T throw");
626 }
627
628 add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
629 {
630 throw std::runtime_error("But this CAN'T throw");
631 }
632};
633
634static void
635test_ref()
636{
637 add_with_throw_on_copy atc;
638 try {
639 boost::function2<int, int, int> f(ref(t&: atc));
640 BOOST_CHECK(f(1, 3) == 4);
641 }
642 catch(std::runtime_error const&) {
643 BOOST_ERROR("Nonthrowing constructor threw an exception");
644 }
645}
646
647static unsigned construction_count = 0;
648static unsigned destruction_count = 0;
649
650struct MySmallFunctor {
651 MySmallFunctor() { ++construction_count; }
652 MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
653 ~MySmallFunctor() { ++destruction_count; }
654 int operator()() { return 0; }
655 };
656
657struct MyLargeFunctor {
658 MyLargeFunctor() { ++construction_count; }
659 MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
660 ~MyLargeFunctor() { ++destruction_count; }
661 int operator()() { return 0; }
662
663 float data[128];
664 };
665
666void test_construct_destroy_count()
667{
668 {
669 boost::function0<int> f;
670 boost::function0<int> g;
671 f = MySmallFunctor();
672 g = MySmallFunctor();
673 f.swap(other&: g);
674 }
675
676 // MySmallFunctor objects should be constructed as many times as
677 // they are destroyed.
678 BOOST_CHECK(construction_count == destruction_count);
679
680 construction_count = 0;
681 destruction_count = 0;
682 {
683 boost::function0<int> f;
684 boost::function0<int> g;
685 f = MyLargeFunctor();
686 g = MyLargeFunctor();
687 f.swap(other&: g);
688 }
689
690 // MyLargeFunctor objects should be constructed as many times as
691 // they are destroyed.
692 BOOST_CHECK(construction_count == destruction_count);
693}
694
695int main()
696{
697 test_zero_args();
698 test_one_arg();
699 test_two_args();
700 test_emptiness();
701 test_member_functions();
702 test_ref();
703 test_construct_destroy_count();
704 return boost::report_errors();
705}
706

source code of boost/libs/function/test/function_n_test.cpp