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