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
36using namespace std;
37using namespace boost;
38
39using namespace boost::lambda;
40
41
42class unary_plus_tester {};
43unary_plus_tester operator+(const unary_plus_tester& a) { return a; }
44
45void 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
83void 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
108void 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
120void 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
138void 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
174void 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
203void 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
299void 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
331class A {};
332
333void 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
361void 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
371void 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
412int 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

source code of boost/libs/lambda/test/operator_tests_simple.cpp