123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813 |
- // Boost.Function library
- // Copyright Douglas Gregor 2001-2003. Use, modification and
- // distribution is subject to the Boost Software License, Version
- // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // For more information, see http://www.boost.org
- #include <boost/function.hpp>
- #include <boost/core/lightweight_test.hpp>
- #include <functional>
- #include <string>
- #include <utility>
- #define BOOST_CHECK BOOST_TEST
- using boost::function;
- using std::string;
- int global_int;
- struct write_five_obj { void operator()() const { global_int = 5; } };
- struct write_three_obj { int operator()() const { global_int = 3; return 7; }};
- static void write_five() { global_int = 5; }
- static void write_three() { global_int = 3; }
- struct generate_five_obj { int operator()() const { return 5; } };
- struct generate_three_obj { int operator()() const { return 3; } };
- static int generate_five() { return 5; }
- static int generate_three() { return 3; }
- static string identity_str(const string& s) { return s; }
- static string string_cat(const string& s1, const string& s2) { return s1+s2; }
- static int sum_ints(int x, int y) { return x+y; }
- struct write_const_1_nonconst_2
- {
- void operator()() { global_int = 2; }
- void operator()() const { global_int = 1; }
- };
- struct add_to_obj
- {
- add_to_obj(int v) : value(v) {}
- int operator()(int x) const { return value + x; }
- int value;
- };
- static void
- test_zero_args()
- {
- typedef function<void ()> func_void_type;
- write_five_obj five;
- write_three_obj three;
- // Default construction
- func_void_type v1;
- BOOST_CHECK(v1.empty());
- // Assignment to an empty function
- v1 = five;
- BOOST_CHECK(v1 != 0);
- // Invocation of a function
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 5);
- // clear() method
- v1.clear();
- BOOST_CHECK(v1 == 0);
- // Assignment to an empty function
- v1 = three;
- BOOST_CHECK(!v1.empty());
- // Invocation and self-assignment
- global_int = 0;
- v1 = v1;
- v1();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v1 = five;
- // Invocation and self-assignment
- global_int = 0;
- v1 = (v1);
- v1();
- BOOST_CHECK(global_int == 5);
- // clear
- v1 = 0;
- BOOST_CHECK(0 == v1);
- // Assignment to an empty function from a free function
- v1 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
- BOOST_CHECK(0 != v1);
- // Invocation
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v1 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
- BOOST_CHECK(!v1.empty());
- // Invocation
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 3);
- // Assignment
- v1 = five;
- BOOST_CHECK(!v1.empty());
- // Invocation
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v1 = &write_three;
- BOOST_CHECK(!v1.empty());
- // Invocation
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 3);
- // Construction from another function (that is empty)
- v1.clear();
- func_void_type v2(v1);
- BOOST_CHECK(!v2? true : false);
- // Assignment to an empty function
- v2 = three;
- BOOST_CHECK(!v2.empty());
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v2 = (five);
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 5);
- v2.clear();
- BOOST_CHECK(v2.empty());
- // Assignment to an empty function from a free function
- v2 = (BOOST_FUNCTION_TARGET_FIX(&) write_five);
- BOOST_CHECK(v2? true : false);
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v2 = BOOST_FUNCTION_TARGET_FIX(&) write_three;
- BOOST_CHECK(!v2.empty());
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 3);
- // Swapping
- v1 = five;
- swap(v1, v2);
- v2();
- BOOST_CHECK(global_int == 5);
- v1();
- BOOST_CHECK(global_int == 3);
- swap(v1, v2);
- v1.clear();
- // Assignment
- v2 = five;
- BOOST_CHECK(!v2.empty());
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v2 = &write_three;
- BOOST_CHECK(!v2.empty());
- // Invocation
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 3);
- // Assignment to a function from an empty function
- v2 = v1;
- BOOST_CHECK(v2.empty());
- // Assignment to a function from a function with a functor
- v1 = three;
- v2 = v1;
- BOOST_CHECK(!v1.empty());
- BOOST_CHECK(!v2.empty());
- // Invocation
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 3);
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 3);
- // Assign to a function from a function with a function
- v2 = BOOST_FUNCTION_TARGET_FIX(&) write_five;
- v1 = v2;
- BOOST_CHECK(!v1.empty());
- BOOST_CHECK(!v2.empty());
- global_int = 0;
- v1();
- BOOST_CHECK(global_int == 5);
- global_int = 0;
- v2();
- BOOST_CHECK(global_int == 5);
- // Construct a function given another function containing a function
- func_void_type v3(v1);
- // Invocation of a function
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 5);
- // clear() method
- v3.clear();
- BOOST_CHECK(!v3? true : false);
- // Assignment to an empty function
- v3 = three;
- BOOST_CHECK(!v3.empty());
- // Invocation
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v3 = five;
- // Invocation
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 5);
- // clear()
- v3.clear();
- BOOST_CHECK(v3.empty());
- // Assignment to an empty function from a free function
- v3 = &write_five;
- BOOST_CHECK(!v3.empty());
- // Invocation
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v3 = &write_three;
- BOOST_CHECK(!v3.empty());
- // Invocation
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 3);
- // Assignment
- v3 = five;
- BOOST_CHECK(!v3.empty());
- // Invocation
- global_int = 0;
- v3();
- BOOST_CHECK(global_int == 5);
- // Construction of a function from a function containing a functor
- func_void_type v4(v3);
- // Invocation of a function
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 5);
- // clear() method
- v4.clear();
- BOOST_CHECK(v4.empty());
- // Assignment to an empty function
- v4 = three;
- BOOST_CHECK(!v4.empty());
- // Invocation
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v4 = five;
- // Invocation
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 5);
- // clear()
- v4.clear();
- BOOST_CHECK(v4.empty());
- // Assignment to an empty function from a free function
- v4 = &write_five;
- BOOST_CHECK(!v4.empty());
- // Invocation
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v4 = &write_three;
- BOOST_CHECK(!v4.empty());
- // Invocation
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 3);
- // Assignment
- v4 = five;
- BOOST_CHECK(!v4.empty());
- // Invocation
- global_int = 0;
- v4();
- BOOST_CHECK(global_int == 5);
- // Construction of a function from a functor
- func_void_type v5(five);
- // Invocation of a function
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 5);
- // clear() method
- v5.clear();
- BOOST_CHECK(v5.empty());
- // Assignment to an empty function
- v5 = three;
- BOOST_CHECK(!v5.empty());
- // Invocation
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v5 = five;
- // Invocation
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 5);
- // clear()
- v5.clear();
- BOOST_CHECK(v5.empty());
- // Assignment to an empty function from a free function
- v5 = &write_five;
- BOOST_CHECK(!v5.empty());
- // Invocation
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v5 = &write_three;
- BOOST_CHECK(!v5.empty());
- // Invocation
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 3);
- // Assignment
- v5 = five;
- BOOST_CHECK(!v5.empty());
- // Invocation
- global_int = 0;
- v5();
- BOOST_CHECK(global_int == 5);
- // Construction of a function from a function
- func_void_type v6(&write_five);
- // Invocation of a function
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 5);
- // clear() method
- v6.clear();
- BOOST_CHECK(v6.empty());
- // Assignment to an empty function
- v6 = three;
- BOOST_CHECK(!v6.empty());
- // Invocation
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 3);
- // Assignment to a non-empty function
- v6 = five;
- // Invocation
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 5);
- // clear()
- v6.clear();
- BOOST_CHECK(v6.empty());
- // Assignment to an empty function from a free function
- v6 = &write_five;
- BOOST_CHECK(!v6.empty());
- // Invocation
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 5);
- // Assignment to a non-empty function from a free function
- v6 = &write_three;
- BOOST_CHECK(!v6.empty());
- // Invocation
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 3);
- // Assignment
- v6 = five;
- BOOST_CHECK(!v6.empty());
- // Invocation
- global_int = 0;
- v6();
- BOOST_CHECK(global_int == 5);
- // Const vs. non-const
- write_const_1_nonconst_2 one_or_two;
- const function<void ()> v7(one_or_two);
- function<void ()> v8(one_or_two);
- global_int = 0;
- v7();
- BOOST_CHECK(global_int == 2);
- global_int = 0;
- v8();
- BOOST_CHECK(global_int == 2);
- // Test construction from 0 and comparison to 0
- func_void_type v9(0);
- BOOST_CHECK(v9 == 0);
- BOOST_CHECK(0 == v9);
- // Test return values
- typedef function<int ()> func_int_type;
- generate_five_obj gen_five;
- generate_three_obj gen_three;
- func_int_type i0(gen_five);
- BOOST_CHECK(i0() == 5);
- i0 = gen_three;
- BOOST_CHECK(i0() == 3);
- i0 = &generate_five;
- BOOST_CHECK(i0() == 5);
- i0 = &generate_three;
- BOOST_CHECK(i0() == 3);
- BOOST_CHECK(i0? true : false);
- i0.clear();
- BOOST_CHECK(!i0? true : false);
- // Test return values with compatible types
- typedef function<long ()> func_long_type;
- func_long_type i1(gen_five);
- BOOST_CHECK(i1() == 5);
- i1 = gen_three;
- BOOST_CHECK(i1() == 3);
- i1 = &generate_five;
- BOOST_CHECK(i1() == 5);
- i1 = &generate_three;
- BOOST_CHECK(i1() == 3);
- BOOST_CHECK(i1? true : false);
- i1.clear();
- BOOST_CHECK(!i1? true : false);
- }
- static void
- test_one_arg()
- {
- std::negate<int> neg;
- function<int (int)> f1(neg);
- BOOST_CHECK(f1(5) == -5);
- function<string (string)> id(&identity_str);
- BOOST_CHECK(id("str") == "str");
- function<string (const char*)> id2(&identity_str);
- BOOST_CHECK(id2("foo") == "foo");
- add_to_obj add_to(5);
- function<int (int)> f2(add_to);
- BOOST_CHECK(f2(3) == 8);
- const function<int (int)> cf2(add_to);
- BOOST_CHECK(cf2(3) == 8);
- }
- static void
- test_two_args()
- {
- function<string (const string&, const string&)> cat(&string_cat);
- BOOST_CHECK(cat("str", "ing") == "string");
- function<int (short, short)> sum(&sum_ints);
- BOOST_CHECK(sum(2, 3) == 5);
- }
- static void
- test_emptiness()
- {
- function<float ()> f1;
- BOOST_CHECK(f1.empty());
- function<float ()> f2;
- f2 = f1;
- BOOST_CHECK(f2.empty());
- function<double ()> f3;
- f3 = f2;
- BOOST_CHECK(f3.empty());
- }
- struct X {
- X(int v) : value(v) {}
- int twice() const { return 2*value; }
- int plus(int v) { return value + v; }
- int value;
- };
- static void
- test_member_functions()
- {
- boost::function<int (X*)> f1(&X::twice);
- X one(1);
- X five(5);
- BOOST_CHECK(f1(&one) == 2);
- BOOST_CHECK(f1(&five) == 10);
- boost::function<int (X*)> f1_2;
- f1_2 = &X::twice;
- BOOST_CHECK(f1_2(&one) == 2);
- BOOST_CHECK(f1_2(&five) == 10);
- boost::function<int (X&, int)> f2(&X::plus);
- BOOST_CHECK(f2(one, 3) == 4);
- BOOST_CHECK(f2(five, 4) == 9);
- }
- struct add_with_throw_on_copy {
- int operator()(int x, int y) const { return x+y; }
- add_with_throw_on_copy() {}
- add_with_throw_on_copy(const add_with_throw_on_copy&)
- {
- throw std::runtime_error("But this CAN'T throw");
- }
- add_with_throw_on_copy& operator=(const add_with_throw_on_copy&)
- {
- throw std::runtime_error("But this CAN'T throw");
- }
- };
- static void
- test_ref()
- {
- add_with_throw_on_copy atc;
- try {
- boost::function<int (int, int)> f(boost::ref(atc));
- BOOST_CHECK(f(1, 3) == 4);
- }
- catch(std::runtime_error const&) {
- BOOST_ERROR("Nonthrowing constructor threw an exception");
- }
- }
- #if BOOST_WORKAROUND(BOOST_GCC, >= 70000 && BOOST_GCC < 80000) && __cplusplus >= 201700
- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81311
- #pragma message("Skipping test_empty_ref on g++ 7 -std=c++17")
- static void test_empty_ref()
- {
- }
- #else
- static void dummy() {}
- static void test_empty_ref()
- {
- boost::function<void()> f1;
- boost::function<void()> f2(boost::ref(f1));
- try {
- f2();
- BOOST_ERROR("Exception didn't throw for reference to empty function.");
- }
- catch(std::runtime_error const&) {}
- f1 = dummy;
- try {
- f2();
- }
- catch(std::runtime_error const&) {
- BOOST_ERROR("Error calling referenced function.");
- }
- }
- #endif
- static void test_exception()
- {
- boost::function<int (int, int)> f;
- try {
- f(5, 4);
- BOOST_CHECK(false);
- }
- catch(boost::bad_function_call const&) {
- // okay
- }
- }
- typedef boost::function< void * (void * reader) > reader_type;
- typedef std::pair<int, reader_type> mapped_type;
- static void test_implicit()
- {
- mapped_type m;
- m = mapped_type();
- }
- static void test_call_obj(boost::function<int (int, int)> f)
- {
- BOOST_CHECK(!f.empty());
- }
- static void test_call_cref(const boost::function<int (int, int)>& f)
- {
- BOOST_CHECK(!f.empty());
- }
- static void test_call()
- {
- test_call_obj(std::plus<int>());
- test_call_cref(std::plus<int>());
- }
- struct big_aggregating_structure {
- int disable_small_objects_optimizations[32];
-
- big_aggregating_structure()
- {
- ++ global_int;
- }
-
- big_aggregating_structure(const big_aggregating_structure&)
- {
- ++ global_int;
- }
- ~big_aggregating_structure()
- {
- -- global_int;
- }
-
- void operator()()
- {
- ++ global_int;
- }
- void operator()(int)
- {
- ++ global_int;
- }
- };
- template <class FunctionT>
- static void test_move_semantics()
- {
- typedef FunctionT f1_type;
- big_aggregating_structure obj;
-
- f1_type f1 = obj;
- global_int = 0;
- f1();
-
- BOOST_CHECK(!f1.empty());
- BOOST_CHECK(global_int == 1);
-
- #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- // Testing rvalue constructors
- f1_type f2(static_cast<f1_type&&>(f1));
- BOOST_CHECK(f1.empty());
- BOOST_CHECK(!f2.empty());
- BOOST_CHECK(global_int == 1);
- f2();
- BOOST_CHECK(global_int == 2);
-
- f1_type f3(static_cast<f1_type&&>(f2));
- BOOST_CHECK(f1.empty());
- BOOST_CHECK(f2.empty());
- BOOST_CHECK(!f3.empty());
- BOOST_CHECK(global_int == 2);
- f3();
- BOOST_CHECK(global_int == 3);
-
- // Testing move assignment
- f1_type f4;
- BOOST_CHECK(f4.empty());
- f4 = static_cast<f1_type&&>(f3);
- BOOST_CHECK(f1.empty());
- BOOST_CHECK(f2.empty());
- BOOST_CHECK(f3.empty());
- BOOST_CHECK(!f4.empty());
- BOOST_CHECK(global_int == 3);
- f4();
- BOOST_CHECK(global_int == 4);
-
- // Testing self move assignment
- f4 = static_cast<f1_type&&>(f4);
- BOOST_CHECK(!f4.empty());
- BOOST_CHECK(global_int == 4);
- // Testing, that no memory leaked when assigning to nonempty function
- f4 = obj;
- BOOST_CHECK(!f4.empty());
- BOOST_CHECK(global_int == 4);
- f1_type f5 = obj;
- BOOST_CHECK(global_int == 5);
- f4 = static_cast<f1_type&&>(f5);
- BOOST_CHECK(global_int == 4);
-
- #endif
- }
- int main()
- {
- test_zero_args();
- test_one_arg();
- test_two_args();
- test_emptiness();
- test_member_functions();
- test_ref();
- test_empty_ref();
- test_exception();
- test_implicit();
- test_call();
- test_move_semantics<function<void()> >();
- test_move_semantics<boost::function0<void> >();
- return boost::report_errors();
- }
|