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
int test_main(int, char* [])
699
test_member_functions();