Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
util-foreach-test.cpp
Go to the documentation of this file.
1/*
2 UtilForeach(Test) - helpers to perform something for each element
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
19#include "lib/test/run.hpp"
20#include "lib/util-foreach.hpp"
21#include "lib/iter-adapter.hpp"
22
23
24#include <boost/lexical_cast.hpp>
25#include <functional>
26#include <iostream>
27#include <vector>
28
29
30using ::Test;
31
32using util::for_each;
33using util::has_any;
34using util::and_all;
35
36using boost::lexical_cast;
37using std::function;
38using std::ref;
39using std::cout;
40using std::endl;
41
42
43namespace util {
44namespace test {
45
46 typedef std::vector<int> VecI;
48
49
50
51 namespace{ // Test data and operations
52
53 // Placeholder for argument in bind-expressions
54 std::_Placeholder<1> _1;
55
56
57 VecI
58 buildTestNumberz (uint count)
59 {
60 VecI numbers;
61 numbers.reserve(count);
62 while (count)
63 numbers.push_back(count--);
64
65 return numbers;
66 }
67
68
69 /* == functions to bind and invoke == */
70 bool
71 plainFunc (int i)
72 {
73 cout <<':'<< i;
74 return i;
75 }
76
77 bool
78 function1 (int i, int j)
79 {
80 return plainFunc(i+j);
81 }
82
83 bool
84 function2 (int i, int j, int& k)
85 {
86 k += i + j;
87 return plainFunc(k);
88 }
89
90
91#define _NL_ cout << endl;
92#define ANNOUNCE(_LABEL_) cout << "---:" << STRINGIFY(_LABEL_) << endl;
93
94 } // (End) test data and operations
95
96
97
98 /*****************************************************************/
112 class UtilForeach_test : public Test
113 {
115
116 virtual void
117 run (Arg arg)
118 {
119 NUM_ELMS = firstVal (arg, 10);
120 VecI container = buildTestNumberz (NUM_ELMS);
121 RangeI iterator(container.begin(), container.end());
122
123 check_foreach_plain (container);
124 check_foreach_plain (iterator);
125
126 check_foreach_bind (container);
127 check_foreach_bind (iterator);
128
129 check_foreach_bind_const (container);
130
131 check_foreach_memFun (container);
132 check_foreach_memFun (iterator);
133
134 check_foreach_lambda (container);
135 check_foreach_lambda (iterator);
136
137 check_existence_quant (container);
138 check_existence_quant (iterator);
139
140 CHECK (int(NUM_ELMS) ==container[0]);
141
142 check_ref_argument_bind (container);
143 CHECK (int(NUM_ELMS) ==container[0]);
144
145 check_ref_argument_bind (iterator);
146 CHECK (90+int(NUM_ELMS) ==container[0]);
147 // changes got propagated through the iterator
148
150
152 }
153
154
159 template<typename CO>
160 void
162 {
164 function<bool(int)> func(plainFunc);
165
166 for_each (coll, plainFunc); _NL_
167 for_each (coll, &plainFunc); _NL_
168 for_each (coll, func); _NL_
169
170 and_all (coll, plainFunc); _NL_
171 and_all (coll, &plainFunc); _NL_
172 and_all (coll, func); _NL_
173
174 has_any (coll, plainFunc); _NL_
175 has_any (coll, &plainFunc); _NL_
176 has_any (coll, func); _NL_
177 }
178
179
183 template<typename CO>
184 void
186 {
188 function<bool(int,int)> fun1(function1);
189
190 for_each (coll, function1, 10, _1 ); _NL_
191 for_each (coll, &function1,10, _1 ); _NL_
192 for_each (coll, fun1, 10, _1 ); _NL_
193
194 and_all (coll, function1, 10, _1 ); _NL_
195 and_all (coll, &function1, 10, _1 ); _NL_
196 and_all (coll, fun1, 10, _1 ); _NL_
197
198 has_any (coll, function1, 10, _1 ); _NL_
199 has_any (coll, &function1, 10, _1 ); _NL_
200 has_any (coll, fun1, 10, _1 ); _NL_
201
202 for_each (coll, function1, _1, _1 ); _NL_
203 for_each (coll, &function1,_1, _1 ); _NL_
204 for_each (coll, fun1, _1, _1 ); _NL_
205
206 and_all (coll, function1, _1, _1 ); _NL_
207 and_all (coll, &function1, _1, _1 ); _NL_
208 and_all (coll, fun1, _1, _1 ); _NL_
209
210 has_any (coll, function1, _1, _1 ); _NL_
211 has_any (coll, &function1, _1, _1 ); _NL_
212 has_any (coll, fun1, _1, _1 ); _NL_
213
214 //does not compile.....
215 // for_each (coll, function1, 10, 20, _1 );
216 // for_each (coll, function1, _1, _2 );
217 // for_each (coll, function1, 10 );
218 }
219
220
233 template<typename CO>
234 void
236 {
237 ANNOUNCE (assign_to_input);
238 function<bool(int,int,int&)> fun2(function2);
239
240 for_each (coll, function2, 5, 5, _1 ); _NL_
241 for_each (coll, &function2,5, 5, _1 ); _NL_
242
243 and_all (coll, function2, 5, 5, _1 ); _NL_
244 and_all (coll, &function2, 5, 5, _1 ); _NL_
245
246 has_any (coll, function2, 5, 5, _1 ); _NL_
247 has_any (coll, &function2, 5, 5, _1 ); _NL_
248
249 // note: in C++11, the reference parameters are passed through
250 // even when wrapping the function or function pointer into a function object,
251 for_each (coll,fun2, 5, 5, _1 ); _NL_
252 and_all (coll, fun2, 5, 5, _1 ); _NL_
253 has_any (coll, fun2, 5, 5, _1 ); _NL_
254 // at that point we have added 9 * (5+5) to the value at position zero.
255 // (note that the has_any only evaluates the function once)
256
257
258 // the following test assigns the sum via the ref argument to a local variable.
259 int sum=0;
260 ANNOUNCE (assign_to_var);
261 for_each (coll, function2, -10, _1, ref(sum) ); _NL_
262 for_each (coll, &function2,-10, _1, ref(sum) ); _NL_
263 for_each (coll, fun2, -10, _1, ref(sum) ); _NL_
264 cout << "sum=" << sum << endl;
265
266 sum=0;
267 and_all (coll, function2, -10, _1, ref(sum) ); _NL_
268 and_all (coll, &function2, -10, _1, ref(sum) ); _NL_
269 and_all (coll, fun2, -10, _1, ref(sum) ); _NL_
270 cout << "sum=" << sum << endl;
271
272 sum=0;
273 has_any (coll, function2, -10, _1, ref(sum) ); _NL_
274 has_any (coll, &function2, -10, _1, ref(sum) ); _NL_
275 has_any (coll, fun2, -10, _1, ref(sum) ); _NL_
276 cout << "sum=" << sum << endl;
277 }
278
279
283 template<typename CO>
284 void
286 {
288
289 for_each (coll,function1, 10, _1 ); _NL_
290 and_all (coll, function1, 10, _1 ); _NL_
291 has_any (coll, function1, 10, _1 ); _NL_
292
293 for_each (coll,function1, _1, _1 ); _NL_
294 and_all (coll, function1, _1, _1 ); _NL_
295 has_any (coll, function1, _1, _1 ); _NL_
296
297 int sum=0;
298
299 for_each (coll,function2, _1, _1, ref(sum) ); _NL_
300 and_all (coll, function2, _1, _1, ref(sum) ); _NL_
301 has_any (coll, function2, _1, _1, ref(sum) ); _NL_
302 }
303
304
305
306 struct Dummy
307 {
308 int sum_;
309
310 bool
311 fun (int i)
312 {
313 sum_ += i;
314 return plainFunc (sum_);
315 }
316 };
317
319 template<typename CO>
320 void
322 {
324
325 Dummy dummy;
326 dummy.sum_ = 0;
327
328 for_each (coll, &Dummy::fun, dummy, _1 ); _NL_
329 and_all (coll, &Dummy::fun, dummy, _1 ); _NL_
330 has_any (coll, &Dummy::fun, dummy, _1 ); _NL_
331
332 for_each (coll, &Dummy::fun, &dummy, _1 ); _NL_
333 and_all (coll, &Dummy::fun, &dummy, _1 ); _NL_
334 has_any (coll, &Dummy::fun, &dummy, _1 ); _NL_
335
336 cout << "sum=" << dummy.sum_ << endl;
337 }
338
339
341 template<typename CO>
342 void
344 {
346 uint sum(0);
347
348 for_each (coll, [&sum] (uint entry) { sum += entry; });
349
350 CHECK (sum == (NUM_ELMS+1) * NUM_ELMS/2);
351
352 CHECK (!and_all (coll, [] (uint elm) { return elm - 1; }));
353 CHECK ( has_any (coll, [] (uint elm) { return elm + 1; }));
354 }
355
356
359 template<typename CO>
360 void
362 {
364
365 CHECK ( and_all (coll, [] (uint elm) { return 0 < elm; }));
366 CHECK (!and_all (coll, [] (uint elm) { return 1 < elm; }));
367
368 CHECK ( has_any (coll, [] (uint elm) { return 0 < elm; }));
369 CHECK ( has_any (coll, [this](uint elm) { return elm == NUM_ELMS; }));
370 CHECK (!has_any (coll, [this](uint elm) { return elm > NUM_ELMS; }));
371 }
372
373
374 struct TestElm
375 {
377 TestElm(uint i) : n_(i) {}
378
379 bool operation() { return plainFunc (n_); }
380 };
381
382
386 void
388 {
390
391 std::vector<TestElm> elms;
392 for (uint i=0; i<6; ++i)
393 elms.push_back (TestElm(i));
394
395 std::vector<TestElm*> elmPtrs;
396 for (uint i=0; i<6; ++i)
397 elmPtrs.push_back (& elms[i]);
398
399 // fed the element pointer as "this" pointer of the member function
400 for_each (elmPtrs, &TestElm::operation, _1 ); _NL_
401 and_all (elmPtrs, &TestElm::operation, _1 ); _NL_
402 has_any (elmPtrs, &TestElm::operation, _1 ); _NL_
403
404 // the same works with copies of the elements as well...
405 for_each (elms, &TestElm::operation, _1 ); _NL_
406 and_all (elms, &TestElm::operation, _1 ); _NL_
407 has_any (elms, &TestElm::operation, _1 ); _NL_
408
409 // note: it seems not to be possible to create a binder, which takes the "*this"-Argument by ref
410 }
411
412
424 void
426 {
427 ANNOUNCE (wrapped_container_passing);
428
429#define SHOW_CONTAINER for_each (coll, plainFunc); _NL_
430
431 int counter = NUM_ELMS;
432 auto assign_and_decrement = [&] (int& entry)
433 {
434 entry = counter--;
435 };
436
437 // use a const reference to pass the container...
438 VecI const& passByConstRef (coll);
439
440 for_each (passByConstRef, assign_and_decrement );
441
443 // indeed got modifications into the original container!
444 CHECK (0 == counter);
445
446 // passing anonymous temporary
447 for_each (buildTestNumberz(NUM_ELMS), assign_and_decrement );
448
449 // passing a smart-ptr managed copy
450 std::shared_ptr<VecI> bySmartPtr (new VecI (coll));
451
452 for_each (bySmartPtr, assign_and_decrement );
453
454 // both didn't influence the original container
456 CHECK (-2*int(NUM_ELMS) == counter);
457 CHECK (bySmartPtr->back() == counter+1);
458
459 // passing the container by pointer is also possible
460 const VecI * const passByConstPointer (&coll);
461
462 for_each (passByConstPointer, assign_and_decrement );
464 // ...and does indeed influence the original container
465 }
466
467 };
468
469
470
471
472 LAUNCHER (UtilForeach_test, "unit common");
473
474
475}} // namespace util::test
476
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
void check_foreach_bind_const(CO const &coll)
void check_wrapped_container_passing(VecI coll)
unsigned int uint
Definition integral.hpp:29
Helper template(s) for creating Lumiera Forward Iterators.
Test runner and basic definitions for tests.
lib::RangeIter< VecI::iterator > RangeI
std::vector< uint > VecI
bool has_any(IT i, IT end, FUN predicate)
Existential quantification: check if any element of a collection satisfies the given predicate.
bool and_all(IT i, IT end, FUN predicate)
All quantification: check if all elements of a collection satisfy the given predicate.
disable_if< can_IterForEach< Container >, FUN > for_each(Container const &coll, FUN doIt)
operate on all elements of a STL container.
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
#define ANNOUNCE(_LABEL_)
#define _NL_
#define SHOW_CONTAINER
Perform operations "for each element" of a collection.