1 | // operator_tests_simple.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 | |
16 | #include <boost/core/lightweight_test.hpp> |
17 | #define BOOST_CHECK BOOST_TEST |
18 | |
19 | #include "boost/lambda/lambda.hpp" |
20 | |
21 | #include "boost/lambda/detail/suppress_unused.hpp" |
22 | |
23 | #include <boost/shared_ptr.hpp> |
24 | |
25 | #include <vector> |
26 | #include <map> |
27 | #include <set> |
28 | #include <string> |
29 | |
30 | #include <iostream> |
31 | |
32 | #ifndef BOOST_NO_STRINGSTREAM |
33 | #include <sstream> |
34 | #endif |
35 | |
36 | using namespace std; |
37 | using namespace boost; |
38 | |
39 | using namespace boost::lambda; |
40 | |
41 | |
42 | class unary_plus_tester {}; |
43 | unary_plus_tester operator+(const unary_plus_tester& a) { return a; } |
44 | |
45 | void cout_tests() |
46 | { |
47 | #ifndef BOOST_NO_STRINGSTREAM |
48 | using std::cout; |
49 | ostringstream os; |
50 | int i = 10; |
51 | (os << _1)(i); |
52 | |
53 | (os << constant(t: "FOO" ))(); |
54 | |
55 | BOOST_CHECK(os.str() == std::string("10FOO" )); |
56 | |
57 | |
58 | istringstream is("ABC 1" ); |
59 | std::string s; |
60 | int k; |
61 | |
62 | is >> s; |
63 | is >> k; |
64 | |
65 | BOOST_CHECK(s == std::string("ABC" )); |
66 | BOOST_CHECK(k == 1); |
67 | // test for constant, constant_ref and var |
68 | i = 5; |
69 | constant_type<int>::type ci(constant(t: i)); |
70 | var_type<int>::type vi(var(t&: i)); |
71 | |
72 | (vi = _1)(make_const(t: 100)); |
73 | BOOST_CHECK((ci)() == 5); |
74 | BOOST_CHECK(i == 100); |
75 | |
76 | int a; |
77 | constant_ref_type<int>::type cr(constant_ref(t: i)); |
78 | (++vi, var(t&: a) = cr)(); |
79 | BOOST_CHECK(i == 101); |
80 | #endif |
81 | } |
82 | |
83 | void arithmetic_operators() { |
84 | int i = 1; int j = 2; int k = 3; |
85 | |
86 | using namespace std; |
87 | using namespace boost::lambda; |
88 | |
89 | BOOST_CHECK((_1 + 1)(i)==2); |
90 | BOOST_CHECK(((_1 + 1) * _2)(i, j)==4); |
91 | BOOST_CHECK((_1 - 1)(i)==0); |
92 | |
93 | BOOST_CHECK((_1 * 2)(j)==4); |
94 | BOOST_CHECK((_1 / 2)(j)==1); |
95 | |
96 | BOOST_CHECK((_1 % 2)(k)==1); |
97 | |
98 | BOOST_CHECK((-_1)(i) == -1); |
99 | BOOST_CHECK((+_1)(i) == 1); |
100 | |
101 | // test that unary plus really does something |
102 | unary_plus_tester u; |
103 | unary_plus_tester up = (+_1)(u); |
104 | |
105 | boost::lambda::detail::suppress_unused_variable_warnings(up); |
106 | } |
107 | |
108 | void bitwise_operators() { |
109 | unsigned int ui = 2; |
110 | |
111 | BOOST_CHECK((_1 << 1)(ui)==(2 << 1)); |
112 | BOOST_CHECK((_1 >> 1)(ui)==(2 >> 1)); |
113 | |
114 | BOOST_CHECK((_1 & 1)(ui)==(2 & 1)); |
115 | BOOST_CHECK((_1 | 1)(ui)==(2 | 1)); |
116 | BOOST_CHECK((_1 ^ 1)(ui)==(2 ^ 1)); |
117 | BOOST_CHECK((~_1)(ui)==~2u); |
118 | } |
119 | |
120 | void comparison_operators() { |
121 | int i = 0, j = 1; |
122 | |
123 | BOOST_CHECK((_1 < _2)(i, j) == true); |
124 | BOOST_CHECK((_1 <= _2)(i, j) == true); |
125 | BOOST_CHECK((_1 == _2)(i, j) == false); |
126 | BOOST_CHECK((_1 != _2)(i, j) == true); |
127 | BOOST_CHECK((_1 > _2)(i, j) == false); |
128 | BOOST_CHECK((_1 >= _2)(i, j) == false); |
129 | |
130 | BOOST_CHECK((!(_1 < _2))(i, j) == false); |
131 | BOOST_CHECK((!(_1 <= _2))(i, j) == false); |
132 | BOOST_CHECK((!(_1 == _2))(i, j) == true); |
133 | BOOST_CHECK((!(_1 != _2))(i, j) == false); |
134 | BOOST_CHECK((!(_1 > _2))(i, j) == true); |
135 | BOOST_CHECK((!(_1 >= _2))(i, j) == true); |
136 | } |
137 | |
138 | void logical_operators() { |
139 | |
140 | bool t = true, f = false; |
141 | BOOST_CHECK((_1 && _2)(t, t) == true); |
142 | BOOST_CHECK((_1 && _2)(t, f) == false); |
143 | BOOST_CHECK((_1 && _2)(f, t) == false); |
144 | BOOST_CHECK((_1 && _2)(f, f) == false); |
145 | |
146 | BOOST_CHECK((_1 || _2)(t, t) == true); |
147 | BOOST_CHECK((_1 || _2)(t, f) == true); |
148 | BOOST_CHECK((_1 || _2)(f, t) == true); |
149 | BOOST_CHECK((_1 || _2)(f, f) == false); |
150 | |
151 | BOOST_CHECK((!_1)(t) == false); |
152 | BOOST_CHECK((!_1)(f) == true); |
153 | |
154 | // test short circuiting |
155 | int i=0; |
156 | |
157 | (false && ++_1)(i); |
158 | BOOST_CHECK(i==0); |
159 | i = 0; |
160 | |
161 | (true && ++_1)(i); |
162 | BOOST_CHECK(i==1); |
163 | i = 0; |
164 | |
165 | (false || ++_1)(i); |
166 | BOOST_CHECK(i==1); |
167 | i = 0; |
168 | |
169 | (true || ++_1)(i); |
170 | BOOST_CHECK(i==0); |
171 | i = 0; |
172 | } |
173 | |
174 | void unary_incs_and_decs() { |
175 | int i = 0; |
176 | |
177 | BOOST_CHECK(_1++(i) == 0); |
178 | BOOST_CHECK(i == 1); |
179 | i = 0; |
180 | |
181 | BOOST_CHECK(_1--(i) == 0); |
182 | BOOST_CHECK(i == -1); |
183 | i = 0; |
184 | |
185 | BOOST_CHECK((++_1)(i) == 1); |
186 | BOOST_CHECK(i == 1); |
187 | i = 0; |
188 | |
189 | BOOST_CHECK((--_1)(i) == -1); |
190 | BOOST_CHECK(i == -1); |
191 | i = 0; |
192 | |
193 | // the result of prefix -- and ++ are lvalues |
194 | (++_1)(i) = 10; |
195 | BOOST_CHECK(i==10); |
196 | i = 0; |
197 | |
198 | (--_1)(i) = 10; |
199 | BOOST_CHECK(i==10); |
200 | i = 0; |
201 | } |
202 | |
203 | void compound_operators() { |
204 | |
205 | int i = 1; |
206 | |
207 | // normal variable as the left operand |
208 | (i += _1)(make_const(t: 1)); |
209 | BOOST_CHECK(i == 2); |
210 | |
211 | (i -= _1)(make_const(t: 1)); |
212 | BOOST_CHECK(i == 1); |
213 | |
214 | (i *= _1)(make_const(t: 10)); |
215 | BOOST_CHECK(i == 10); |
216 | |
217 | (i /= _1)(make_const(t: 2)); |
218 | BOOST_CHECK(i == 5); |
219 | |
220 | (i %= _1)(make_const(t: 2)); |
221 | BOOST_CHECK(i == 1); |
222 | |
223 | // lambda expression as a left operand |
224 | (_1 += 1)(i); |
225 | BOOST_CHECK(i == 2); |
226 | |
227 | (_1 -= 1)(i); |
228 | BOOST_CHECK(i == 1); |
229 | |
230 | (_1 *= 10)(i); |
231 | BOOST_CHECK(i == 10); |
232 | |
233 | (_1 /= 2)(i); |
234 | BOOST_CHECK(i == 5); |
235 | |
236 | (_1 %= 2)(i); |
237 | BOOST_CHECK(i == 1); |
238 | |
239 | // lambda expression as a left operand with rvalue on RHS |
240 | (_1 += (0 + 1))(i); |
241 | BOOST_CHECK(i == 2); |
242 | |
243 | (_1 -= (0 + 1))(i); |
244 | BOOST_CHECK(i == 1); |
245 | |
246 | (_1 *= (0 + 10))(i); |
247 | BOOST_CHECK(i == 10); |
248 | |
249 | (_1 /= (0 + 2))(i); |
250 | BOOST_CHECK(i == 5); |
251 | |
252 | (_1 %= (0 + 2))(i); |
253 | BOOST_CHECK(i == 1); |
254 | |
255 | // shifts |
256 | unsigned int ui = 2; |
257 | (_1 <<= 1)(ui); |
258 | BOOST_CHECK(ui==(2 << 1)); |
259 | |
260 | ui = 2; |
261 | (_1 >>= 1)(ui); |
262 | BOOST_CHECK(ui==(2 >> 1)); |
263 | |
264 | ui = 2; |
265 | (ui <<= _1)(make_const(t: 1)); |
266 | BOOST_CHECK(ui==(2 << 1)); |
267 | |
268 | ui = 2; |
269 | (ui >>= _1)(make_const(t: 1)); |
270 | BOOST_CHECK(ui==(2 >> 1)); |
271 | |
272 | // and, or, xor |
273 | ui = 2; |
274 | (_1 &= 1)(ui); |
275 | BOOST_CHECK(ui==(2 & 1)); |
276 | |
277 | ui = 2; |
278 | (_1 |= 1)(ui); |
279 | BOOST_CHECK(ui==(2 | 1)); |
280 | |
281 | ui = 2; |
282 | (_1 ^= 1)(ui); |
283 | BOOST_CHECK(ui==(2 ^ 1)); |
284 | |
285 | ui = 2; |
286 | (ui &= _1)(make_const(t: 1)); |
287 | BOOST_CHECK(ui==(2 & 1)); |
288 | |
289 | ui = 2; |
290 | (ui |= _1)(make_const(t: 1)); |
291 | BOOST_CHECK(ui==(2 | 1)); |
292 | |
293 | ui = 2; |
294 | (ui ^= _1)(make_const(t: 1)); |
295 | BOOST_CHECK(ui==(2 ^ 1)); |
296 | |
297 | } |
298 | |
299 | void assignment_and_subscript() { |
300 | |
301 | // assignment and subscript need to be defined as member functions. |
302 | // Hence, if you wish to use a normal variable as the left hand argument, |
303 | // you must wrap it with var to turn it into a lambda expression |
304 | |
305 | using std::string; |
306 | string s; |
307 | |
308 | (_1 = "one" )(s); |
309 | BOOST_CHECK(s == string("one" )); |
310 | |
311 | (var(t&: s) = "two" )(); |
312 | BOOST_CHECK(s == string("two" )); |
313 | |
314 | BOOST_CHECK((var(s)[_1])(make_const(2)) == 'o'); |
315 | BOOST_CHECK((_1[2])(s) == 'o'); |
316 | BOOST_CHECK((_1[_2])(s, make_const(2)) == 'o'); |
317 | |
318 | // subscript returns lvalue |
319 | (var(t&: s)[_1])(make_const(t: 1)) = 'o'; |
320 | BOOST_CHECK(s == "too" ); |
321 | |
322 | (_1[1])(s) = 'a'; |
323 | BOOST_CHECK(s == "tao" ); |
324 | |
325 | (_1[_2])(s, make_const(t: 0)) = 'm'; |
326 | BOOST_CHECK(s == "mao" ); |
327 | |
328 | // TODO: tests for vector, set, map, multimap |
329 | } |
330 | |
331 | class A {}; |
332 | |
333 | void address_of_and_dereference() { |
334 | |
335 | A a; int i = 42; |
336 | |
337 | BOOST_CHECK((&_1)(a) == &a); |
338 | BOOST_CHECK((*&_1)(i) == 42); |
339 | |
340 | std::vector<int> vi; vi.push_back(x: 1); |
341 | std::vector<int>::iterator it = vi.begin(); |
342 | |
343 | (*_1 = 7)(it); |
344 | BOOST_CHECK(vi[0] == 7); |
345 | const std::vector<int>::iterator cit(it); |
346 | (*_1 = 8)(cit); |
347 | BOOST_CHECK(vi[0] == 8); |
348 | |
349 | // TODO: Add tests for more complex iterator types |
350 | |
351 | boost::shared_ptr<int> ptr(new int(0)); |
352 | (*_1 = 7)(ptr); |
353 | BOOST_CHECK(*ptr == 7); |
354 | const boost::shared_ptr<int> cptr(ptr); |
355 | (*_1 = 8)(cptr); |
356 | BOOST_CHECK(*ptr == 8); |
357 | } |
358 | |
359 | |
360 | |
361 | void comma() { |
362 | |
363 | int i = 100; |
364 | BOOST_CHECK((_1 = 10, 2 * _1)(i) == 20); |
365 | |
366 | // TODO: that the return type is the exact type of the right argument |
367 | // (that r/l valueness is preserved) |
368 | |
369 | } |
370 | |
371 | void pointer_arithmetic() { |
372 | |
373 | int ia[4] = { 1, 2, 3, 4 }; |
374 | int* ip = ia; |
375 | int* ia_last = &ia[3]; |
376 | |
377 | const int cia[4] = { 1, 2, 3, 4 }; |
378 | const int* cip = cia; |
379 | const int* cia_last = &cia[3]; |
380 | |
381 | |
382 | // non-const array |
383 | BOOST_CHECK((*(_1 + 1))(ia) == 2); |
384 | |
385 | // non-const pointer |
386 | BOOST_CHECK((*(_1 + 1))(ip) == 2); |
387 | |
388 | BOOST_CHECK((*(_1 - 1))(ia_last) == 3); |
389 | |
390 | // const array |
391 | BOOST_CHECK((*(_1 + 1))(cia) == 2); |
392 | // const pointer |
393 | BOOST_CHECK((*(_1 + 1))(cip) == 2); |
394 | BOOST_CHECK((*(_1 - 1))(cia_last) == 3); |
395 | |
396 | // pointer arithmetic should not make non-consts const |
397 | (*(_1 + 2))(ia) = 0; |
398 | (*(_1 + 3))(ip) = 0; |
399 | |
400 | BOOST_CHECK(ia[2] == 0); |
401 | BOOST_CHECK(ia[3] == 0); |
402 | |
403 | // pointer - pointer |
404 | BOOST_CHECK((_1 - _2)(ia_last, ia) == 3); |
405 | BOOST_CHECK((_1 - _2)(cia_last, cia) == 3); |
406 | BOOST_CHECK((ia_last - _1)(ia) == 3); |
407 | BOOST_CHECK((cia_last - _1)(cia) == 3); |
408 | BOOST_CHECK((cia_last - _1)(cip) == 3); |
409 | |
410 | } |
411 | |
412 | int main() { |
413 | |
414 | arithmetic_operators(); |
415 | bitwise_operators(); |
416 | comparison_operators(); |
417 | logical_operators(); |
418 | unary_incs_and_decs(); |
419 | compound_operators(); |
420 | assignment_and_subscript(); |
421 | address_of_and_dereference(); |
422 | comma(); |
423 | pointer_arithmetic(); |
424 | cout_tests(); |
425 | return boost::report_errors(); |
426 | } |
427 | |