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