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 #if defined(__clang__) && defined(__has_warning)
11 # if __has_warning( "-Wself-assign-overloaded" )
12 # pragma clang diagnostic ignored "-Wself-assign-overloaded"
16 #include <boost/function.hpp>
17 #include <boost/core/lightweight_test.hpp>
22 #define BOOST_CHECK BOOST_TEST
24 using boost::function
;
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
; }
41 struct write_const_1_nonconst_2
43 void operator()() { global_int
= 2; }
44 void operator()() const { global_int
= 1; }
49 add_to_obj(int v
) : value(v
) {}
51 int operator()(int x
) const { return value
+ x
; }
59 typedef function
<void ()> func_void_type
;
62 write_three_obj three
;
64 // Default construction
66 BOOST_CHECK(v1
.empty());
68 // Assignment to an empty function
72 // Invocation of a function
75 BOOST_CHECK(global_int
== 5);
81 // Assignment to an empty function
83 BOOST_CHECK(!v1
.empty());
85 // Invocation and self-assignment
89 BOOST_CHECK(global_int
== 3);
91 // Assignment to a non-empty function
94 // Invocation and self-assignment
98 BOOST_CHECK(global_int
== 5);
102 BOOST_CHECK(0 == v1
);
104 // Assignment to an empty function from a free function
105 v1
= BOOST_FUNCTION_TARGET_FIX(&) write_five
;
106 BOOST_CHECK(0 != v1
);
111 BOOST_CHECK(global_int
== 5);
113 // Assignment to a non-empty function from a free function
114 v1
= BOOST_FUNCTION_TARGET_FIX(&) write_three
;
115 BOOST_CHECK(!v1
.empty());
120 BOOST_CHECK(global_int
== 3);
124 BOOST_CHECK(!v1
.empty());
129 BOOST_CHECK(global_int
== 5);
131 // Assignment to a non-empty function from a free function
133 BOOST_CHECK(!v1
.empty());
138 BOOST_CHECK(global_int
== 3);
140 // Construction from another function (that is empty)
142 func_void_type
v2(v1
);
143 BOOST_CHECK(!v2
? true : false);
145 // Assignment to an empty function
147 BOOST_CHECK(!v2
.empty());
152 BOOST_CHECK(global_int
== 3);
154 // Assignment to a non-empty function
160 BOOST_CHECK(global_int
== 5);
163 BOOST_CHECK(v2
.empty());
165 // Assignment to an empty function from a free function
166 v2
= (BOOST_FUNCTION_TARGET_FIX(&) write_five
);
167 BOOST_CHECK(v2
? true : false);
172 BOOST_CHECK(global_int
== 5);
174 // Assignment to a non-empty function from a free function
175 v2
= BOOST_FUNCTION_TARGET_FIX(&) write_three
;
176 BOOST_CHECK(!v2
.empty());
181 BOOST_CHECK(global_int
== 3);
187 BOOST_CHECK(global_int
== 5);
189 BOOST_CHECK(global_int
== 3);
195 BOOST_CHECK(!v2
.empty());
200 BOOST_CHECK(global_int
== 5);
202 // Assignment to a non-empty function from a free function
204 BOOST_CHECK(!v2
.empty());
209 BOOST_CHECK(global_int
== 3);
211 // Assignment to a function from an empty function
213 BOOST_CHECK(v2
.empty());
215 // Assignment to a function from a function with a functor
218 BOOST_CHECK(!v1
.empty());
219 BOOST_CHECK(!v2
.empty());
224 BOOST_CHECK(global_int
== 3);
227 BOOST_CHECK(global_int
== 3);
229 // Assign to a function from a function with a function
230 v2
= BOOST_FUNCTION_TARGET_FIX(&) write_five
;
232 BOOST_CHECK(!v1
.empty());
233 BOOST_CHECK(!v2
.empty());
236 BOOST_CHECK(global_int
== 5);
239 BOOST_CHECK(global_int
== 5);
241 // Construct a function given another function containing a function
242 func_void_type
v3(v1
);
244 // Invocation of a function
247 BOOST_CHECK(global_int
== 5);
251 BOOST_CHECK(!v3
? true : false);
253 // Assignment to an empty function
255 BOOST_CHECK(!v3
.empty());
260 BOOST_CHECK(global_int
== 3);
262 // Assignment to a non-empty function
268 BOOST_CHECK(global_int
== 5);
272 BOOST_CHECK(v3
.empty());
274 // Assignment to an empty function from a free function
276 BOOST_CHECK(!v3
.empty());
281 BOOST_CHECK(global_int
== 5);
283 // Assignment to a non-empty function from a free function
285 BOOST_CHECK(!v3
.empty());
290 BOOST_CHECK(global_int
== 3);
294 BOOST_CHECK(!v3
.empty());
299 BOOST_CHECK(global_int
== 5);
301 // Construction of a function from a function containing a functor
302 func_void_type
v4(v3
);
304 // Invocation of a function
307 BOOST_CHECK(global_int
== 5);
311 BOOST_CHECK(v4
.empty());
313 // Assignment to an empty function
315 BOOST_CHECK(!v4
.empty());
320 BOOST_CHECK(global_int
== 3);
322 // Assignment to a non-empty function
328 BOOST_CHECK(global_int
== 5);
332 BOOST_CHECK(v4
.empty());
334 // Assignment to an empty function from a free function
336 BOOST_CHECK(!v4
.empty());
341 BOOST_CHECK(global_int
== 5);
343 // Assignment to a non-empty function from a free function
345 BOOST_CHECK(!v4
.empty());
350 BOOST_CHECK(global_int
== 3);
354 BOOST_CHECK(!v4
.empty());
359 BOOST_CHECK(global_int
== 5);
361 // Construction of a function from a functor
362 func_void_type
v5(five
);
364 // Invocation of a function
367 BOOST_CHECK(global_int
== 5);
371 BOOST_CHECK(v5
.empty());
373 // Assignment to an empty function
375 BOOST_CHECK(!v5
.empty());
380 BOOST_CHECK(global_int
== 3);
382 // Assignment to a non-empty function
388 BOOST_CHECK(global_int
== 5);
392 BOOST_CHECK(v5
.empty());
394 // Assignment to an empty function from a free function
396 BOOST_CHECK(!v5
.empty());
401 BOOST_CHECK(global_int
== 5);
403 // Assignment to a non-empty function from a free function
405 BOOST_CHECK(!v5
.empty());
410 BOOST_CHECK(global_int
== 3);
414 BOOST_CHECK(!v5
.empty());
419 BOOST_CHECK(global_int
== 5);
421 // Construction of a function from a function
422 func_void_type
v6(&write_five
);
424 // Invocation of a function
427 BOOST_CHECK(global_int
== 5);
431 BOOST_CHECK(v6
.empty());
433 // Assignment to an empty function
435 BOOST_CHECK(!v6
.empty());
440 BOOST_CHECK(global_int
== 3);
442 // Assignment to a non-empty function
448 BOOST_CHECK(global_int
== 5);
452 BOOST_CHECK(v6
.empty());
454 // Assignment to an empty function from a free function
456 BOOST_CHECK(!v6
.empty());
461 BOOST_CHECK(global_int
== 5);
463 // Assignment to a non-empty function from a free function
465 BOOST_CHECK(!v6
.empty());
470 BOOST_CHECK(global_int
== 3);
474 BOOST_CHECK(!v6
.empty());
479 BOOST_CHECK(global_int
== 5);
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
);
488 BOOST_CHECK(global_int
== 2);
492 BOOST_CHECK(global_int
== 2);
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
);
499 // Test return values
500 typedef function
<int ()> func_int_type
;
501 generate_five_obj gen_five
;
502 generate_three_obj gen_three
;
504 func_int_type
i0(gen_five
);
506 BOOST_CHECK(i0() == 5);
508 BOOST_CHECK(i0() == 3);
510 BOOST_CHECK(i0() == 5);
511 i0
= &generate_three
;
512 BOOST_CHECK(i0() == 3);
513 BOOST_CHECK(i0
? true : false);
515 BOOST_CHECK(!i0
? true : false);
517 // Test return values with compatible types
518 typedef function
<long ()> func_long_type
;
519 func_long_type
i1(gen_five
);
521 BOOST_CHECK(i1() == 5);
523 BOOST_CHECK(i1() == 3);
525 BOOST_CHECK(i1() == 5);
526 i1
= &generate_three
;
527 BOOST_CHECK(i1() == 3);
528 BOOST_CHECK(i1
? true : false);
530 BOOST_CHECK(!i1
? true : false);
536 std::negate
<int> neg
;
538 function
<int (int)> f1(neg
);
539 BOOST_CHECK(f1(5) == -5);
541 function
<string (string
)> id(&identity_str
);
542 BOOST_CHECK(id("str") == "str");
544 function
<string (const char*)> id2(&identity_str
);
545 BOOST_CHECK(id2("foo") == "foo");
547 add_to_obj
add_to(5);
548 function
<int (int)> f2(add_to
);
549 BOOST_CHECK(f2(3) == 8);
551 const function
<int (int)> cf2(add_to
);
552 BOOST_CHECK(cf2(3) == 8);
558 function
<string (const string
&, const string
&)> cat(&string_cat
);
559 BOOST_CHECK(cat("str", "ing") == "string");
561 function
<int (short, short)> sum(&sum_ints
);
562 BOOST_CHECK(sum(2, 3) == 5);
568 function
<float ()> f1
;
569 BOOST_CHECK(f1
.empty());
571 function
<float ()> f2
;
573 BOOST_CHECK(f2
.empty());
575 function
<double ()> f3
;
577 BOOST_CHECK(f3
.empty());
581 X(int v
) : value(v
) {}
583 int twice() const { return 2*value
; }
584 int plus(int v
) { return value
+ v
; }
590 test_member_functions()
592 boost::function
<int (X
*)> f1(&X::twice
);
597 BOOST_CHECK(f1(&one
) == 2);
598 BOOST_CHECK(f1(&five
) == 10);
600 boost::function
<int (X
*)> f1_2
;
603 BOOST_CHECK(f1_2(&one
) == 2);
604 BOOST_CHECK(f1_2(&five
) == 10);
606 boost::function
<int (X
&, int)> f2(&X::plus
);
607 BOOST_CHECK(f2(one
, 3) == 4);
608 BOOST_CHECK(f2(five
, 4) == 9);
611 struct add_with_throw_on_copy
{
612 int operator()(int x
, int y
) const { return x
+y
; }
614 add_with_throw_on_copy() {}
616 add_with_throw_on_copy(const add_with_throw_on_copy
&)
618 throw std::runtime_error("But this CAN'T throw");
621 add_with_throw_on_copy
& operator=(const add_with_throw_on_copy
&)
623 throw std::runtime_error("But this CAN'T throw");
630 add_with_throw_on_copy atc
;
632 boost::function
<int (int, int)> f(boost::ref(atc
));
633 BOOST_CHECK(f(1, 3) == 4);
635 catch(std::runtime_error
const&) {
636 BOOST_ERROR("Nonthrowing constructor threw an exception");
640 #if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700
642 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311
643 #pragma message("Skipping test_empty_ref on g++ 7 -std=c++17")
645 static void test_empty_ref()
651 static void dummy() {}
653 static void test_empty_ref()
655 boost::function
<void()> f1
;
656 boost::function
<void()> f2(boost::ref(f1
));
660 BOOST_ERROR("Exception didn't throw for reference to empty function.");
662 catch(std::runtime_error
const&) {}
669 catch(std::runtime_error
const&) {
670 BOOST_ERROR("Error calling referenced function.");
677 static void test_exception()
679 boost::function
<int (int, int)> f
;
684 catch(boost::bad_function_call
const&) {
689 typedef boost::function
< void * (void * reader
) > reader_type
;
690 typedef std::pair
<int, reader_type
> mapped_type
;
692 static void test_implicit()
698 static void test_call_obj(boost::function
<int (int, int)> f
)
700 BOOST_CHECK(!f
.empty());
703 static void test_call_cref(const boost::function
<int (int, int)>& f
)
705 BOOST_CHECK(!f
.empty());
708 static void test_call()
710 test_call_obj(std::plus
<int>());
711 test_call_cref(std::plus
<int>());
714 struct big_aggregating_structure
{
715 int disable_small_objects_optimizations
[32];
717 big_aggregating_structure()
722 big_aggregating_structure(const big_aggregating_structure
&)
727 ~big_aggregating_structure()
743 template <class FunctionT
>
744 static void test_move_semantics()
746 typedef FunctionT f1_type
;
748 big_aggregating_structure obj
;
754 BOOST_CHECK(!f1
.empty());
755 BOOST_CHECK(global_int
== 1);
757 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
758 // Testing rvalue constructors
759 f1_type
f2(static_cast<f1_type
&&>(f1
));
760 BOOST_CHECK(f1
.empty());
761 BOOST_CHECK(!f2
.empty());
762 BOOST_CHECK(global_int
== 1);
764 BOOST_CHECK(global_int
== 2);
766 f1_type
f3(static_cast<f1_type
&&>(f2
));
767 BOOST_CHECK(f1
.empty());
768 BOOST_CHECK(f2
.empty());
769 BOOST_CHECK(!f3
.empty());
770 BOOST_CHECK(global_int
== 2);
772 BOOST_CHECK(global_int
== 3);
774 // Testing move assignment
776 BOOST_CHECK(f4
.empty());
777 f4
= static_cast<f1_type
&&>(f3
);
778 BOOST_CHECK(f1
.empty());
779 BOOST_CHECK(f2
.empty());
780 BOOST_CHECK(f3
.empty());
781 BOOST_CHECK(!f4
.empty());
782 BOOST_CHECK(global_int
== 3);
784 BOOST_CHECK(global_int
== 4);
786 // Testing self move assignment
787 f4
= static_cast<f1_type
&&>(f4
);
788 BOOST_CHECK(!f4
.empty());
789 BOOST_CHECK(global_int
== 4);
791 // Testing, that no memory leaked when assigning to nonempty function
793 BOOST_CHECK(!f4
.empty());
794 BOOST_CHECK(global_int
== 4);
796 BOOST_CHECK(global_int
== 5);
797 f4
= static_cast<f1_type
&&>(f5
);
798 BOOST_CHECK(global_int
== 4);
809 test_member_functions();
815 test_move_semantics
<function
<void()> >();
816 test_move_semantics
<boost::function0
<void> >();
818 return boost::report_errors();