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
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 {};
operator +(const unary_plus_tester & a)42 unary_plus_tester operator+(const unary_plus_tester& a) { return a; }
43
cout_tests()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_TEST_EQ(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_TEST_EQ(s, std::string("ABC"));
65 BOOST_TEST_EQ(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_TEST_EQ((ci)(), 5);
73 BOOST_TEST_EQ(i, 100);
74
75 int a;
76 constant_ref_type<int>::type cr(constant_ref(i));
77 (++vi, var(a) = cr)();
78 BOOST_TEST_EQ(i, 101);
79 #endif
80 }
81
arithmetic_operators()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_TEST_EQ((_1 + 1)(i), 2);
89 BOOST_TEST_EQ(((_1 + 1) * _2)(i, j), 4);
90 BOOST_TEST_EQ((_1 - 1)(i), 0);
91
92 BOOST_TEST_EQ((_1 * 2)(j), 4);
93 BOOST_TEST_EQ((_1 / 2)(j), 1);
94
95 BOOST_TEST_EQ((_1 % 2)(k), 1);
96
97 BOOST_TEST_EQ((-_1)(i), -1);
98 BOOST_TEST_EQ((+_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
bitwise_operators()107 void bitwise_operators() {
108 unsigned int ui = 2;
109
110 BOOST_TEST_EQ((_1 << 1)(ui), (2 << 1));
111 BOOST_TEST_EQ((_1 >> 1)(ui), (2 >> 1));
112
113 BOOST_TEST_EQ((_1 & 1)(ui), (2 & 1));
114 BOOST_TEST_EQ((_1 | 1)(ui), (2 | 1));
115 BOOST_TEST_EQ((_1 ^ 1)(ui), (2 ^ 1));
116 BOOST_TEST_EQ((~_1)(ui), ~2u);
117 }
118
comparison_operators()119 void comparison_operators() {
120 int i = 0, j = 1;
121
122 BOOST_TEST((_1 < _2)(i, j));
123 BOOST_TEST((_1 <= _2)(i, j));
124 BOOST_TEST(!(_1 == _2)(i, j));
125 BOOST_TEST((_1 != _2)(i, j));
126 BOOST_TEST(!(_1 > _2)(i, j));
127 BOOST_TEST(!(_1 >= _2)(i, j));
128
129 BOOST_TEST(!(!(_1 < _2))(i, j));
130 BOOST_TEST(!(!(_1 <= _2))(i, j));
131 BOOST_TEST((!(_1 == _2))(i, j));
132 BOOST_TEST(!(!(_1 != _2))(i, j));
133 BOOST_TEST((!(_1 > _2))(i, j));
134 BOOST_TEST((!(_1 >= _2))(i, j));
135 }
136
logical_operators()137 void logical_operators() {
138
139 bool t = true, f = false;
140 BOOST_TEST((_1 && _2)(t, t));
141 BOOST_TEST(!(_1 && _2)(t, f));
142 BOOST_TEST(!(_1 && _2)(f, t));
143 BOOST_TEST(!(_1 && _2)(f, f));
144
145 BOOST_TEST((_1 || _2)(t, t));
146 BOOST_TEST((_1 || _2)(t, f));
147 BOOST_TEST((_1 || _2)(f, t));
148 BOOST_TEST(!(_1 || _2)(f, f));
149
150 BOOST_TEST(!(!_1)(t));
151 BOOST_TEST((!_1)(f));
152
153 // test short circuiting
154 int i=0;
155
156 (false && ++_1)(i);
157 BOOST_TEST_EQ(i, 0);
158 i = 0;
159
160 (true && ++_1)(i);
161 BOOST_TEST_EQ(i, 1);
162 i = 0;
163
164 (false || ++_1)(i);
165 BOOST_TEST_EQ(i, 1);
166 i = 0;
167
168 (true || ++_1)(i);
169 BOOST_TEST_EQ(i, 0);
170 i = 0;
171 }
172
unary_incs_and_decs()173 void unary_incs_and_decs() {
174 int i = 0;
175
176 BOOST_TEST_EQ(_1++(i), 0);
177 BOOST_TEST_EQ(i, 1);
178 i = 0;
179
180 BOOST_TEST_EQ(_1--(i), 0);
181 BOOST_TEST_EQ(i, -1);
182 i = 0;
183
184 BOOST_TEST_EQ((++_1)(i), 1);
185 BOOST_TEST_EQ(i, 1);
186 i = 0;
187
188 BOOST_TEST_EQ((--_1)(i), -1);
189 BOOST_TEST_EQ(i, -1);
190 i = 0;
191
192 // the result of prefix -- and ++ are lvalues
193 (++_1)(i) = 10;
194 BOOST_TEST_EQ(i, 10);
195 i = 0;
196
197 (--_1)(i) = 10;
198 BOOST_TEST_EQ(i, 10);
199 i = 0;
200 }
201
compound_operators()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_TEST_EQ(i, 2);
209
210 (i -= _1)(make_const(1));
211 BOOST_TEST_EQ(i, 1);
212
213 (i *= _1)(make_const(10));
214 BOOST_TEST_EQ(i, 10);
215
216 (i /= _1)(make_const(2));
217 BOOST_TEST_EQ(i, 5);
218
219 (i %= _1)(make_const(2));
220 BOOST_TEST_EQ(i, 1);
221
222 // lambda expression as a left operand
223 (_1 += 1)(i);
224 BOOST_TEST_EQ(i, 2);
225
226 (_1 -= 1)(i);
227 BOOST_TEST_EQ(i, 1);
228
229 (_1 *= 10)(i);
230 BOOST_TEST_EQ(i, 10);
231
232 (_1 /= 2)(i);
233 BOOST_TEST_EQ(i, 5);
234
235 (_1 %= 2)(i);
236 BOOST_TEST_EQ(i, 1);
237
238 // lambda expression as a left operand with rvalue on RHS
239 (_1 += (0 + 1))(i);
240 BOOST_TEST_EQ(i, 2);
241
242 (_1 -= (0 + 1))(i);
243 BOOST_TEST_EQ(i, 1);
244
245 (_1 *= (0 + 10))(i);
246 BOOST_TEST_EQ(i, 10);
247
248 (_1 /= (0 + 2))(i);
249 BOOST_TEST_EQ(i, 5);
250
251 (_1 %= (0 + 2))(i);
252 BOOST_TEST_EQ(i, 1);
253
254 // shifts
255 unsigned int ui = 2;
256 (_1 <<= 1)(ui);
257 BOOST_TEST_EQ(ui, (2 << 1));
258
259 ui = 2;
260 (_1 >>= 1)(ui);
261 BOOST_TEST_EQ(ui, (2 >> 1));
262
263 ui = 2;
264 (ui <<= _1)(make_const(1));
265 BOOST_TEST_EQ(ui, (2 << 1));
266
267 ui = 2;
268 (ui >>= _1)(make_const(1));
269 BOOST_TEST_EQ(ui, (2 >> 1));
270
271 // and, or, xor
272 ui = 2;
273 (_1 &= 1)(ui);
274 BOOST_TEST_EQ(ui, (2 & 1));
275
276 ui = 2;
277 (_1 |= 1)(ui);
278 BOOST_TEST_EQ(ui, (2 | 1));
279
280 ui = 2;
281 (_1 ^= 1)(ui);
282 BOOST_TEST_EQ(ui, (2 ^ 1));
283
284 ui = 2;
285 (ui &= _1)(make_const(1));
286 BOOST_TEST_EQ(ui, (2 & 1));
287
288 ui = 2;
289 (ui |= _1)(make_const(1));
290 BOOST_TEST_EQ(ui, (2 | 1));
291
292 ui = 2;
293 (ui ^= _1)(make_const(1));
294 BOOST_TEST_EQ(ui, (2 ^ 1));
295
296 }
297
assignment_and_subscript()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_TEST_EQ(s, string("one"));
309
310 (var(s) = "two")();
311 BOOST_TEST_EQ(s, string("two"));
312
313 BOOST_TEST_EQ((var(s)[_1])(make_const(2)), 'o');
314 BOOST_TEST_EQ((_1[2])(s), 'o');
315 BOOST_TEST_EQ((_1[_2])(s, make_const(2)), 'o');
316
317 // subscript returns lvalue
318 (var(s)[_1])(make_const(1)) = 'o';
319 BOOST_TEST_EQ(s, "too");
320
321 (_1[1])(s) = 'a';
322 BOOST_TEST_EQ(s, "tao");
323
324 (_1[_2])(s, make_const(0)) = 'm';
325 BOOST_TEST_EQ(s, "mao");
326
327 // TODO: tests for vector, set, map, multimap
328 }
329
330 class A {};
331
address_of_and_dereference()332 void address_of_and_dereference() {
333
334 A a; int i = 42;
335
336 BOOST_TEST_EQ((&_1)(a), &a);
337 BOOST_TEST_EQ((*&_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_TEST_EQ(vi[0], 7);
344 const std::vector<int>::iterator cit(it);
345 (*_1 = 8)(cit);
346 BOOST_TEST_EQ(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_TEST_EQ(*ptr, 7);
353 const boost::shared_ptr<int> cptr(ptr);
354 (*_1 = 8)(cptr);
355 BOOST_TEST_EQ(*ptr, 8);
356 }
357
358
359
comma()360 void comma() {
361
362 int i = 100;
363 BOOST_TEST_EQ((_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
pointer_arithmetic()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_TEST_EQ((*(_1 + 1))(ia), 2);
383
384 // non-const pointer
385 BOOST_TEST_EQ((*(_1 + 1))(ip), 2);
386
387 BOOST_TEST_EQ((*(_1 - 1))(ia_last), 3);
388
389 // const array
390 BOOST_TEST_EQ((*(_1 + 1))(cia), 2);
391 // const pointer
392 BOOST_TEST_EQ((*(_1 + 1))(cip), 2);
393 BOOST_TEST_EQ((*(_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_TEST_EQ(ia[2], 0);
400 BOOST_TEST_EQ(ia[3], 0);
401
402 // pointer - pointer
403 BOOST_TEST_EQ((_1 - _2)(ia_last, ia), 3);
404 BOOST_TEST_EQ((_1 - _2)(cia_last, cia), 3);
405 BOOST_TEST_EQ((ia_last - _1)(ia), 3);
406 BOOST_TEST_EQ((cia_last - _1)(cia), 3);
407 BOOST_TEST_EQ((cia_last - _1)(cip), 3);
408
409 }
410
main()411 int main()
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 boost::report_errors();
425 }
426