]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // member_pointer_test.cpp -- The Boost Lambda Library ------------------ |
2 | // | |
3 | // Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) | |
4 | // Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com) | |
5 | // | |
6 | // Distributed under the Boost Software License, Version 1.0. (See | |
7 | // accompanying file LICENSE_1_0.txt or copy at | |
8 | // http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | // For more information, see www.boost.org | |
11 | ||
12 | // ----------------------------------------------------------------------- | |
13 | ||
14 | ||
15 | #include <boost/test/minimal.hpp> // see "Header Implementation Option" | |
16 | ||
17 | ||
18 | #include "boost/lambda/lambda.hpp" | |
19 | #include "boost/lambda/bind.hpp" | |
20 | ||
21 | #include <string> | |
22 | ||
23 | using namespace boost::lambda; | |
24 | using namespace std; | |
25 | ||
26 | ||
27 | struct my_struct { | |
28 | my_struct(int x) : mem(x) {}; | |
29 | ||
30 | int mem; | |
31 | ||
32 | int fooc() const { return mem; } | |
33 | int foo() { return mem; } | |
34 | int foo1c(int y) const { return y + mem; } | |
35 | int foo1(int y) { return y + mem; } | |
36 | int foo2c(int y, int x) const { return y + x + mem; } | |
37 | int foo2(int y, int x) { return y + x + mem; } | |
38 | int foo3c(int y, int x, int z) const { return y + x + z + mem; } | |
39 | int foo3(int y, int x, int z ){ return y + x + z + mem; } | |
40 | int foo4c(int a1, int a2, int a3, int a4) const { return a1+a2+a3+a4+mem; } | |
41 | int foo4(int a1, int a2, int a3, int a4){ return a1+a2+a3+a4+mem; } | |
42 | ||
43 | int foo3default(int y = 1, int x = 2, int z = 3) { return y + x + z + mem; } | |
44 | }; | |
45 | ||
46 | my_struct x(3); | |
47 | ||
48 | void pointer_to_data_member_tests() { | |
49 | ||
50 | // int i = 0; | |
51 | my_struct *y = &x; | |
52 | ||
53 | BOOST_CHECK((_1 ->* &my_struct::mem)(y) == 3); | |
54 | ||
55 | (_1 ->* &my_struct::mem)(y) = 4; | |
56 | BOOST_CHECK(x.mem == 4); | |
57 | ||
58 | ((_1 ->* &my_struct::mem) = 5)(y); | |
59 | BOOST_CHECK(x.mem == 5); | |
60 | ||
61 | // &my_struct::mem is a temporary, must be constified | |
62 | ((y ->* _1) = 6)(make_const(&my_struct::mem)); | |
63 | BOOST_CHECK(x.mem == 6); | |
64 | ||
65 | ((_1 ->* _2) = 7)(y, make_const(&my_struct::mem)); | |
66 | BOOST_CHECK(x.mem == 7); | |
67 | ||
68 | } | |
69 | ||
70 | void pointer_to_member_function_tests() { | |
71 | ||
72 | my_struct *y = new my_struct(1); | |
73 | BOOST_CHECK( (_1 ->* &my_struct::foo)(y)() == (y->mem)); | |
74 | BOOST_CHECK( (_1 ->* &my_struct::fooc)(y)() == (y->mem)); | |
75 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo))() == (y->mem)); | |
76 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::fooc))() == (y->mem)); | |
77 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo))() == (y->mem)); | |
78 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::fooc))() == (y->mem)); | |
79 | ||
80 | BOOST_CHECK( (_1 ->* &my_struct::foo1)(y)(1) == (y->mem+1)); | |
81 | BOOST_CHECK( (_1 ->* &my_struct::foo1c)(y)(1) == (y->mem+1)); | |
82 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1))(1) == (y->mem+1)); | |
83 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo1c))(1) == (y->mem+1)); | |
84 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1))(1) == (y->mem+1)); | |
85 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo1c))(1) == (y->mem+1)); | |
86 | ||
87 | BOOST_CHECK( (_1 ->* &my_struct::foo2)(y)(1,2) == (y->mem+1+2)); | |
88 | BOOST_CHECK( (_1 ->* &my_struct::foo2c)(y)(1,2) == (y->mem+1+2)); | |
89 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2))(1,2) == (y->mem+1+2)); | |
90 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2)); | |
91 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2))(1,2) == (y->mem+1+2)); | |
92 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo2c))(1,2) == (y->mem+1+2)); | |
93 | ||
94 | BOOST_CHECK( (_1 ->* &my_struct::foo3)(y)(1,2,3) == (y->mem+1+2+3)); | |
95 | BOOST_CHECK( (_1 ->* &my_struct::foo3c)(y)(1,2,3) == (y->mem+1+2+3)); | |
96 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3)); | |
97 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3)); | |
98 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3))(1,2,3) == (y->mem+1+2+3)); | |
99 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo3c))(1,2,3) == (y->mem+1+2+3)); | |
100 | ||
101 | BOOST_CHECK( (_1 ->* &my_struct::foo4)(y)(1,2,3,4) == (y->mem+1+2+3+4)); | |
102 | BOOST_CHECK( (_1 ->* &my_struct::foo4c)(y)(1,2,3,4) == (y->mem+1+2+3+4)); | |
103 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4)); | |
104 | BOOST_CHECK( (y ->* _1)(make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4)); | |
105 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4))(1,2,3,4) == (y->mem+1+2+3+4)); | |
106 | BOOST_CHECK( (_1 ->* _2)(y, make_const(&my_struct::foo4c))(1,2,3,4) == (y->mem+1+2+3+4)); | |
107 | ||
108 | ||
109 | ||
110 | // member functions with default values do not work (inherent language issue) | |
111 | // BOOST_CHECK( (_1 ->* &my_struct::foo3default)(y)() == (y->mem+1+2+3)); | |
112 | ||
113 | } | |
114 | ||
115 | class A {}; | |
116 | class B {}; | |
117 | class C {}; | |
118 | class D {}; | |
119 | ||
120 | // ->* can be overloaded to do anything | |
121 | bool operator->*(A /*a*/, B /*b*/) { | |
122 | return false; | |
123 | } | |
124 | ||
125 | bool operator->*(B /*b*/, A /*a*/) { | |
126 | return true; | |
127 | } | |
128 | ||
129 | // let's provide specializations to take care of the return type deduction. | |
130 | // Note, that you need to provide all four cases for non-const and const | |
131 | // or use the plain_return_type_2 template. | |
132 | namespace boost { | |
133 | namespace lambda { | |
134 | ||
135 | template <> | |
136 | struct return_type_2<other_action<member_pointer_action>, B, A> { | |
137 | typedef bool type; | |
138 | }; | |
139 | ||
140 | template<> | |
141 | struct return_type_2<other_action<member_pointer_action>, const B, A> { | |
142 | typedef bool type; | |
143 | }; | |
144 | ||
145 | template<> | |
146 | struct return_type_2<other_action<member_pointer_action>, B, const A> { | |
147 | typedef bool type; | |
148 | }; | |
149 | ||
150 | template<> | |
151 | struct return_type_2<other_action<member_pointer_action>, const B, const A> { | |
152 | typedef bool type; | |
153 | }; | |
154 | ||
155 | ||
156 | ||
157 | ||
158 | } // lambda | |
159 | } // boost | |
160 | ||
161 | void test_overloaded_pointer_to_member() | |
162 | { | |
163 | A a; B b; | |
164 | ||
165 | // this won't work, can't deduce the return type | |
166 | // BOOST_CHECK((_1->*_2)(a, b) == false); | |
167 | ||
168 | // ret<bool> gives the return type | |
169 | BOOST_CHECK(ret<bool>(_1->*_2)(a, b) == false); | |
170 | BOOST_CHECK(ret<bool>(a->*_1)(b) == false); | |
171 | BOOST_CHECK(ret<bool>(_1->*b)(a) == false); | |
172 | BOOST_CHECK((ret<bool>((var(a))->*b))() == false); | |
173 | BOOST_CHECK((ret<bool>((var(a))->*var(b)))() == false); | |
174 | ||
175 | ||
176 | // this is ok without ret<bool> due to the return_type_2 spcialization above | |
177 | BOOST_CHECK((_1->*_2)(b, a) == true); | |
178 | BOOST_CHECK((b->*_1)(a) == true); | |
179 | BOOST_CHECK((_1->*a)(b) == true); | |
180 | BOOST_CHECK((var(b)->*a)() == true); | |
181 | return; | |
182 | } | |
183 | ||
184 | ||
185 | int test_main(int, char *[]) { | |
186 | ||
187 | pointer_to_data_member_tests(); | |
188 | pointer_to_member_function_tests(); | |
189 | test_overloaded_pointer_to_member(); | |
190 | return 0; | |
191 | } | |
192 |