1 // Boost.Function library
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)
8 // For more information, see http://www.boost.org
10 #include <boost/test/minimal.hpp>
11 #include <boost/function.hpp>
16 using boost::function;
21 struct write_five_obj { void operator()() const { global_int = 5; } };
22 struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
23 static void write_five() { global_int = 5; }
24 static void write_three() { global_int = 3; }
25 struct generate_five_obj { int operator()() const { return 5; } };
26 struct generate_three_obj { int operator()() const { return 3; } };
27 static int generate_five() { return 5; }
28 static int generate_three() { return 3; }
29 static string identity_str(const string& s) { return s; }
30 static string string_cat(const string& s1, const string& s2) { return s1+s2; }
31 static int sum_ints(int x, int y) { return x+y; }
33 struct write_const_1_nonconst_2
35 void operator()() { global_int = 2; }
36 void operator()() const { global_int = 1; }
41 add_to_obj(int v) : value(v) {}
43 int operator()(int x) const { return value + x; }
51 typedef function<void ()> func_void_type;
54 write_three_obj three;
56 // Default construction
58 BOOST_CHECK(v1.empty());
60 // Assignment to an empty function
64 // Invocation of a function
67 BOOST_CHECK(global_int == 5);
73 // Assignment to an empty function
75 BOOST_CHECK(!v1.empty());
77 // Invocation and self-assignment
81 BOOST_CHECK(global_int == 3);
83 // Assignment to a non-empty function
86 // Invocation and self-assignment
90 BOOST_CHECK(global_int == 5);
96 // Assignment to an empty function from a free function
97 v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
103 BOOST_CHECK(global_int == 5);
105 // Assignment to a non-empty function from a free function
106 v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
107 BOOST_CHECK(!v1.empty());
112 BOOST_CHECK(global_int == 3);
116 BOOST_CHECK(!v1.empty());
121 BOOST_CHECK(global_int == 5);
123 // Assignment to a non-empty function from a free function
125 BOOST_CHECK(!v1.empty());
130 BOOST_CHECK(global_int == 3);
132 // Construction from another function (that is empty)
134 func_void_type v2(v1);
135 BOOST_CHECK(!v2? true : false);
137 // Assignment to an empty function
139 BOOST_CHECK(!v2.empty());
144 BOOST_CHECK(global_int == 3);
146 // Assignment to a non-empty function
152 BOOST_CHECK(global_int == 5);
155 BOOST_CHECK(v2.empty());
157 // Assignment to an empty function from a free function
158 v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
159 BOOST_CHECK(v2? true : false);
164 BOOST_CHECK(global_int == 5);
166 // Assignment to a non-empty function from a free function
167 v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
168 BOOST_CHECK(!v2.empty());
173 BOOST_CHECK(global_int == 3);
179 BOOST_CHECK(global_int == 5);
181 BOOST_CHECK(global_int == 3);
187 BOOST_CHECK(!v2.empty());
192 BOOST_CHECK(global_int == 5);
194 // Assignment to a non-empty function from a free function
196 BOOST_CHECK(!v2.empty());
201 BOOST_CHECK(global_int == 3);
203 // Assignment to a function from an empty function
205 BOOST_CHECK(v2.empty());
207 // Assignment to a function from a function with a functor
210 BOOST_CHECK(!v1.empty());
211 BOOST_CHECK(!v2.empty());
216 BOOST_CHECK(global_int == 3);
219 BOOST_CHECK(global_int == 3);
221 // Assign to a function from a function with a function
222 v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
224 BOOST_CHECK(!v1.empty());
225 BOOST_CHECK(!v2.empty());
228 BOOST_CHECK(global_int == 5);
231 BOOST_CHECK(global_int == 5);
233 // Construct a function given another function containing a function
234 func_void_type v3(v1);
236 // Invocation of a function
239 BOOST_CHECK(global_int == 5);
243 BOOST_CHECK(!v3? true : false);
245 // Assignment to an empty function
247 BOOST_CHECK(!v3.empty());
252 BOOST_CHECK(global_int == 3);
254 // Assignment to a non-empty function
260 BOOST_CHECK(global_int == 5);
264 BOOST_CHECK(v3.empty());
266 // Assignment to an empty function from a free function
268 BOOST_CHECK(!v3.empty());
273 BOOST_CHECK(global_int == 5);
275 // Assignment to a non-empty function from a free function
277 BOOST_CHECK(!v3.empty());
282 BOOST_CHECK(global_int == 3);
286 BOOST_CHECK(!v3.empty());
291 BOOST_CHECK(global_int == 5);
293 // Construction of a function from a function containing a functor
294 func_void_type v4(v3);
296 // Invocation of a function
299 BOOST_CHECK(global_int == 5);
303 BOOST_CHECK(v4.empty());
305 // Assignment to an empty function
307 BOOST_CHECK(!v4.empty());
312 BOOST_CHECK(global_int == 3);
314 // Assignment to a non-empty function
320 BOOST_CHECK(global_int == 5);
324 BOOST_CHECK(v4.empty());
326 // Assignment to an empty function from a free function
328 BOOST_CHECK(!v4.empty());
333 BOOST_CHECK(global_int == 5);
335 // Assignment to a non-empty function from a free function
337 BOOST_CHECK(!v4.empty());
342 BOOST_CHECK(global_int == 3);
346 BOOST_CHECK(!v4.empty());
351 BOOST_CHECK(global_int == 5);
353 // Construction of a function from a functor
354 func_void_type v5(five);
356 // Invocation of a function
359 BOOST_CHECK(global_int == 5);
363 BOOST_CHECK(v5.empty());
365 // Assignment to an empty function
367 BOOST_CHECK(!v5.empty());
372 BOOST_CHECK(global_int == 3);
374 // Assignment to a non-empty function
380 BOOST_CHECK(global_int == 5);
384 BOOST_CHECK(v5.empty());
386 // Assignment to an empty function from a free function
388 BOOST_CHECK(!v5.empty());
393 BOOST_CHECK(global_int == 5);
395 // Assignment to a non-empty function from a free function
397 BOOST_CHECK(!v5.empty());
402 BOOST_CHECK(global_int == 3);
406 BOOST_CHECK(!v5.empty());
411 BOOST_CHECK(global_int == 5);
413 // Construction of a function from a function
414 func_void_type v6(&write_five);
416 // Invocation of a function
419 BOOST_CHECK(global_int == 5);
423 BOOST_CHECK(v6.empty());
425 // Assignment to an empty function
427 BOOST_CHECK(!v6.empty());
432 BOOST_CHECK(global_int == 3);
434 // Assignment to a non-empty function
440 BOOST_CHECK(global_int == 5);
444 BOOST_CHECK(v6.empty());
446 // Assignment to an empty function from a free function
448 BOOST_CHECK(!v6.empty());
453 BOOST_CHECK(global_int == 5);
455 // Assignment to a non-empty function from a free function
457 BOOST_CHECK(!v6.empty());
462 BOOST_CHECK(global_int == 3);
466 BOOST_CHECK(!v6.empty());
471 BOOST_CHECK(global_int == 5);
473 // Const vs. non-const
474 write_const_1_nonconst_2 one_or_two;
475 const function<void ()> v7(one_or_two);
476 function<void ()> v8(one_or_two);
480 BOOST_CHECK(global_int == 2);
484 BOOST_CHECK(global_int == 2);
486 // Test construction from 0 and comparison to 0
487 func_void_type v9(0);
488 BOOST_CHECK(v9 == 0);
489 BOOST_CHECK(0 == v9);
491 // Test return values
492 typedef function<int ()> func_int_type;
493 generate_five_obj gen_five;
494 generate_three_obj gen_three;
496 func_int_type i0(gen_five);
498 BOOST_CHECK(i0() == 5);
500 BOOST_CHECK(i0() == 3);
502 BOOST_CHECK(i0() == 5);
503 i0 = &generate_three;
504 BOOST_CHECK(i0() == 3);
505 BOOST_CHECK(i0? true : false);
507 BOOST_CHECK(!i0? true : false);
509 // Test return values with compatible types
510 typedef function<long ()> func_long_type;
511 func_long_type i1(gen_five);
513 BOOST_CHECK(i1() == 5);
515 BOOST_CHECK(i1() == 3);
517 BOOST_CHECK(i1() == 5);
518 i1 = &generate_three;
519 BOOST_CHECK(i1() == 3);
520 BOOST_CHECK(i1? true : false);
522 BOOST_CHECK(!i1? true : false);
528 std::negate<int> neg;
530 function<int (int)> f1(neg);
531 BOOST_CHECK(f1(5) == -5);
533 function<string (string)> id(&identity_str);
534 BOOST_CHECK(id("str") == "str");
536 function<string (const char*)> id2(&identity_str);
537 BOOST_CHECK(id2("foo") == "foo");
539 add_to_obj add_to(5);
540 function<int (int)> f2(add_to);
541 BOOST_CHECK(f2(3) == 8);
543 const function<int (int)> cf2(add_to);
544 BOOST_CHECK(cf2(3) == 8);
550 function<string (const string&, const string&)> cat(&string_cat);
551 BOOST_CHECK(cat("str", "ing") == "string");
553 function<int (short, short)> sum(&sum_ints);
554 BOOST_CHECK(sum(2, 3) == 5);
560 function<float ()> f1;
561 BOOST_CHECK(f1.empty());
563 function<float ()> f2;
565 BOOST_CHECK(f2.empty());
567 function<double ()> f3;
569 BOOST_CHECK(f3.empty());
573 X(int v) : value(v) {}
575 int twice() const { return 2*value; }
576 int plus(int v) { return value + v; }
582 test_member_functions()
584 boost::function<int (X*)> f1(&X::twice);
589 BOOST_CHECK(f1(&one) == 2);
590 BOOST_CHECK(f1(&five) == 10);
592 boost::function<int (X*)> f1_2;
595 BOOST_CHECK(f1_2(&one) == 2);
596 BOOST_CHECK(f1_2(&five) == 10);
598 boost::function<int (X&, int)> f2(&X::plus);
599 BOOST_CHECK(f2(one, 3) == 4);
600 BOOST_CHECK(f2(five, 4) == 9);
603 struct add_with_throw_on_copy {
604 int operator()(int x, int y) const { return x+y; }
606 add_with_throw_on_copy() {}
608 add_with_throw_on_copy(const add_with_throw_on_copy&)
610 throw std::runtime_error("But this CAN'T throw");
613 add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
615 throw std::runtime_error("But this CAN'T throw");
622 add_with_throw_on_copy atc;
624 boost::function<int (int, int)> f(boost::ref(atc));
625 BOOST_CHECK(f(1, 3) == 4);
627 catch(std::runtime_error e) {
628 BOOST_ERROR("Nonthrowing constructor threw an exception");
632 static void dummy() {}
634 static void test_empty_ref()
636 boost::function<void()> f1;
637 boost::function<void()> f2(boost::ref(f1));
641 BOOST_ERROR("Exception didn't throw for reference to empty function.");
643 catch(std::runtime_error e) {}
650 catch(std::runtime_error e) {
651 BOOST_ERROR("Error calling referenced function.");
656 static void test_exception()
658 boost::function<int (int, int)> f;
663 catch(boost::bad_function_call) {
668 typedef boost::function< void * (void * reader) > reader_type;
669 typedef std::pair<int, reader_type> mapped_type;
671 static void test_implicit()
677 static void test_call_obj(boost::function<int (int, int)> f)
679 BOOST_CHECK(!f.empty());
682 static void test_call_cref(const boost::function<int (int, int)>& f)
684 BOOST_CHECK(!f.empty());
687 static void test_call()
689 test_call_obj(std::plus<int>());
690 test_call_cref(std::plus<int>());
693 struct big_aggregating_structure {
694 int disable_small_objects_optimizations[32];
696 big_aggregating_structure()
701 big_aggregating_structure(const big_aggregating_structure&)
706 ~big_aggregating_structure()
722 template <class FunctionT>
723 static void test_move_semantics()
725 typedef FunctionT f1_type;
727 big_aggregating_structure obj;
733 BOOST_CHECK(!f1.empty());
734 BOOST_CHECK(global_int == 1);
736 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
737 // Testing rvalue constructors
738 f1_type f2(static_cast<f1_type&&>(f1));
739 BOOST_CHECK(f1.empty());
740 BOOST_CHECK(!f2.empty());
741 BOOST_CHECK(global_int == 1);
743 BOOST_CHECK(global_int == 2);
745 f1_type f3(static_cast<f1_type&&>(f2));
746 BOOST_CHECK(f1.empty());
747 BOOST_CHECK(f2.empty());
748 BOOST_CHECK(!f3.empty());
749 BOOST_CHECK(global_int == 2);
751 BOOST_CHECK(global_int == 3);
753 // Testing move assignment
755 BOOST_CHECK(f4.empty());
756 f4 = static_cast<f1_type&&>(f3);
757 BOOST_CHECK(f1.empty());
758 BOOST_CHECK(f2.empty());
759 BOOST_CHECK(f3.empty());
760 BOOST_CHECK(!f4.empty());
761 BOOST_CHECK(global_int == 3);
763 BOOST_CHECK(global_int == 4);
765 // Testing self move assignment
766 f4 = static_cast<f1_type&&>(f4);
767 BOOST_CHECK(!f4.empty());
768 BOOST_CHECK(global_int == 4);
770 // Testing, that no memory leaked when assigning to nonempty function
772 BOOST_CHECK(!f4.empty());
773 BOOST_CHECK(global_int == 4);
775 BOOST_CHECK(global_int == 5);
776 f4 = static_cast<f1_type&&>(f5);
777 BOOST_CHECK(global_int == 4);
782 int test_main(int, char* [])
788 test_member_functions();
794 test_move_semantics<function<void()> >();
795 test_move_semantics<boost::function0<void> >();