#if defined(__clang__) && defined(__has_warning)
# if __has_warning( "-Wself-assign-overloaded" )
# pragma clang diagnostic ignored "-Wself-assign-overloaded"
# endif
#endif
#include <boost/function.hpp>
#include <boost/core/lightweight_test.hpp>
#include <functional>
#include <cassert>
#include <string>
#define BOOST_CHECK BOOST_TEST
using namespace boost;
using std::string;
using std::negate;
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 function0<void> func_void_type;
write_five_obj five = write_five_obj(); write_three_obj three = write_three_obj();
func_void_type v1;
BOOST_CHECK(v1.empty());
v1 = five;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
v1.clear();
BOOST_CHECK(!v1);
v1 = three;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1 = v1;
v1();
BOOST_CHECK(global_int == 3);
v1 = five;
global_int = 0;
v1 = (v1);
v1();
BOOST_CHECK(global_int == 5);
v1 = 0;
BOOST_CHECK(v1.empty());
v1 = &write_five;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
v1 = &write_three;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
v1 = five;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 5);
v1 = write_three;
BOOST_CHECK(!v1.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
v1.clear();
func_void_type v2(v1);
BOOST_CHECK(!v2? true : false);
v2 = three;
BOOST_CHECK(!v2.empty());
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
v2 = (five);
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
v2.clear();
BOOST_CHECK(v2.empty());
v2 = (&write_five);
BOOST_CHECK(v2? true : false);
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
v2 = &write_three;
BOOST_CHECK(!v2.empty());
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
v1 = five;
swap(v1, v2);
v2();
BOOST_CHECK(global_int == 5);
v1();
BOOST_CHECK(global_int == 3);
swap(v1, v2);
v1.clear();
v2 = five;
BOOST_CHECK(!v2.empty());
global_int = 0;
v2();
BOOST_CHECK(global_int == 5);
v2 = &write_three;
BOOST_CHECK(!v2.empty());
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
v2 = v1;
BOOST_CHECK(v2.empty());
v1 = three;
v2 = v1;
BOOST_CHECK(!v1.empty());
BOOST_CHECK(!v2.empty());
global_int = 0;
v1();
BOOST_CHECK(global_int == 3);
global_int = 0;
v2();
BOOST_CHECK(global_int == 3);
v2 = &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);
func_void_type v3(v1);
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
v3.clear();
BOOST_CHECK(!v3? true : false);
v3 = three;
BOOST_CHECK(!v3.empty());
global_int = 0;
v3();
BOOST_CHECK(global_int == 3);
v3 = five;
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
v3.clear();
BOOST_CHECK(v3.empty());
v3 = &write_five;
BOOST_CHECK(!v3.empty());
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
v3 = &write_three;
BOOST_CHECK(!v3.empty());
global_int = 0;
v3();
BOOST_CHECK(global_int == 3);
v3 = five;
BOOST_CHECK(!v3.empty());
global_int = 0;
v3();
BOOST_CHECK(global_int == 5);
func_void_type v4(v3);
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
v4.clear();
BOOST_CHECK(v4.empty());
v4 = three;
BOOST_CHECK(!v4.empty());
global_int = 0;
v4();
BOOST_CHECK(global_int == 3);
v4 = five;
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
v4.clear();
BOOST_CHECK(v4.empty());
v4 = &write_five;
BOOST_CHECK(!v4.empty());
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
v4 = &write_three;
BOOST_CHECK(!v4.empty());
global_int = 0;
v4();
BOOST_CHECK(global_int == 3);
v4 = five;
BOOST_CHECK(!v4.empty());
global_int = 0;
v4();
BOOST_CHECK(global_int == 5);
func_void_type v5(five);
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
v5.clear();
BOOST_CHECK(v5.empty());
v5 = three;
BOOST_CHECK(!v5.empty());
global_int = 0;
v5();
BOOST_CHECK(global_int == 3);
v5 = five;
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
v5.clear();
BOOST_CHECK(v5.empty());
v5 = &write_five;
BOOST_CHECK(!v5.empty());
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
v5 = &write_three;
BOOST_CHECK(!v5.empty());
global_int = 0;
v5();
BOOST_CHECK(global_int == 3);
v5 = five;
BOOST_CHECK(!v5.empty());
global_int = 0;
v5();
BOOST_CHECK(global_int == 5);
func_void_type v6(&write_five);
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
v6.clear();
BOOST_CHECK(v6.empty());
v6 = three;
BOOST_CHECK(!v6.empty());
global_int = 0;
v6();
BOOST_CHECK(global_int == 3);
v6 = five;
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
v6.clear();
BOOST_CHECK(v6.empty());
v6 = &write_five;
BOOST_CHECK(!v6.empty());
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
v6 = &write_three;
BOOST_CHECK(!v6.empty());
global_int = 0;
v6();
BOOST_CHECK(global_int == 3);
v6 = five;
BOOST_CHECK(!v6.empty());
global_int = 0;
v6();
BOOST_CHECK(global_int == 5);
write_const_1_nonconst_2 one_or_two = write_const_1_nonconst_2();
const function0<void> v7(one_or_two);
function0<void> v8(one_or_two);
global_int = 0;
v7();
BOOST_CHECK(global_int == 2);
global_int = 0;
v8();
BOOST_CHECK(global_int == 2);
func_void_type v9(0);
BOOST_CHECK(v9 == 0);
# if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540 || defined(BOOST_STRICT_CONFIG)
BOOST_CHECK(0 == v9);
#else
BOOST_CHECK(v9.empty());
#endif
typedef function0<int> func_int_type;
generate_five_obj gen_five = generate_five_obj();
generate_three_obj gen_three = generate_three_obj();
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);
typedef function0<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()
{
negate<int> neg = negate<int>();
function1<int, int> f1(neg);
BOOST_CHECK(f1(5) == -5);
function1<string, string> id(&identity_str);
BOOST_CHECK(id("str") == "str");
function1<std::string, const char*> id2(&identity_str);
BOOST_CHECK(id2("foo") == "foo");
add_to_obj add_to(5);
function1<int, int> f2(add_to);
BOOST_CHECK(f2(3) == 8);
const function1<int, int> cf2(add_to);
BOOST_CHECK(cf2(3) == 8);
}
static void
test_two_args()
{
function2<string, const string&, const string&> cat(&string_cat);
BOOST_CHECK(cat("str", "ing") == "string");
function2<int, short, short> sum(&sum_ints);
BOOST_CHECK(sum(2, 3) == 5);
}
static void
test_emptiness()
{
function0<float> f1;
BOOST_CHECK(f1.empty());
function0<float> f2;
f2 = f1;
BOOST_CHECK(f2.empty());
function0<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::function1<int, X*> f1(&X::twice);
X one(1);
X five(5);
BOOST_CHECK(f1(&one) == 2);
BOOST_CHECK(f1(&five) == 10);
boost::function1<int, X*> f1_2;
f1_2 = &X::twice;
BOOST_CHECK(f1_2(&one) == 2);
BOOST_CHECK(f1_2(&five) == 10);
boost::function2<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::function2<int, int, int> f(ref(atc));
BOOST_CHECK(f(1, 3) == 4);
}
catch(std::runtime_error const&) {
BOOST_ERROR("Nonthrowing constructor threw an exception");
}
}
static unsigned construction_count = 0;
static unsigned destruction_count = 0;
struct MySmallFunctor {
MySmallFunctor() { ++construction_count; }
MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
~MySmallFunctor() { ++destruction_count; }
int operator()() { return 0; }
};
struct MyLargeFunctor {
MyLargeFunctor() { ++construction_count; }
MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
~MyLargeFunctor() { ++destruction_count; }
int operator()() { return 0; }
float data[128];
};
void test_construct_destroy_count()
{
{
boost::function0<int> f;
boost::function0<int> g;
f = MySmallFunctor();
g = MySmallFunctor();
f.swap(g);
}
BOOST_CHECK(construction_count == destruction_count);
construction_count = 0;
destruction_count = 0;
{
boost::function0<int> f;
boost::function0<int> g;
f = MyLargeFunctor();
g = MyLargeFunctor();
f.swap(g);
}
BOOST_CHECK(construction_count == destruction_count);
}
int main()
{
test_zero_args();
test_one_arg();
test_two_args();
test_emptiness();
test_member_functions();
test_ref();
test_construct_destroy_count();
return boost::report_errors();
}