1 | // -- exception_test.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 | #include <boost/core/lightweight_test.hpp> |
15 | #define BOOST_CHECK BOOST_TEST |
16 | |
17 | #include "boost/lambda/lambda.hpp" |
18 | |
19 | #include "boost/lambda/exceptions.hpp" |
20 | |
21 | #include "boost/lambda/bind.hpp" |
22 | |
23 | #include<iostream> |
24 | #include<algorithm> |
25 | #include <cstdlib> |
26 | |
27 | #include <iostream> |
28 | |
29 | using namespace boost::lambda; |
30 | using namespace std; |
31 | |
32 | // to prevent unused variables warnings |
33 | template <class T> void dummy(const T&) {} |
34 | |
35 | void erroneous_exception_related_lambda_expressions() { |
36 | |
37 | int i = 0; |
38 | dummy(i); |
39 | |
40 | // Uncommenting any of the below code lines should result in a compile |
41 | // time error |
42 | |
43 | // this should fail (a rethrow binder outside of catch |
44 | // rethrow()(); |
45 | |
46 | // this should fail too for the same reason |
47 | // try_catch(rethrow(), catch_all(cout << constant("Howdy")))(); |
48 | |
49 | // this fails too (_e outside of catch_exception) |
50 | // (_1 + _2 + _e)(i, i, i); |
51 | |
52 | // and this (_e outside of catch_exception) |
53 | // try_catch( throw_exception(1), catch_all(cout << _e)); |
54 | |
55 | // and this (_3 in catch_exception |
56 | // try_catch( throw_exception(1), catch_exception<int>(cout << _3)); |
57 | } |
58 | |
59 | |
60 | class A1 {}; |
61 | class A2 {}; |
62 | class A3 {}; |
63 | class A4 {}; |
64 | class A5 {}; |
65 | class A6 {}; |
66 | class A7 {}; |
67 | class A8 {}; |
68 | class A9 {}; |
69 | |
70 | void throw_AX(int j) { |
71 | int i = j; |
72 | switch(i) { |
73 | case 1: throw A1(); |
74 | case 2: throw A2(); |
75 | case 3: throw A3(); |
76 | case 4: throw A4(); |
77 | case 5: throw A5(); |
78 | case 6: throw A6(); |
79 | case 7: throw A7(); |
80 | case 8: throw A8(); |
81 | case 9: throw A9(); |
82 | } |
83 | } |
84 | |
85 | void test_different_number_of_catch_blocks() { |
86 | |
87 | int ecount; |
88 | |
89 | // no catch(...) cases |
90 | |
91 | |
92 | ecount = 0; |
93 | for(int i=1; i<=1; i++) |
94 | { |
95 | try_catch( |
96 | a1: bind(a1&: throw_AX, a2: _1), |
97 | a2: catch_exception<A1>( |
98 | a: var(t&: ecount)++ |
99 | ) |
100 | )(i); |
101 | } |
102 | BOOST_CHECK(ecount == 1); |
103 | |
104 | ecount = 0; |
105 | for(int i=1; i<=2; i++) |
106 | { |
107 | try_catch( |
108 | a1: bind(a1&: throw_AX, a2: _1), |
109 | a2: catch_exception<A1>( |
110 | a: var(t&: ecount)++ |
111 | ), |
112 | a3: catch_exception<A2>( |
113 | a: var(t&: ecount)++ |
114 | ) |
115 | )(i); |
116 | } |
117 | BOOST_CHECK(ecount == 2); |
118 | |
119 | ecount = 0; |
120 | for(int i=1; i<=3; i++) |
121 | { |
122 | try_catch( |
123 | a1: bind(a1&: throw_AX, a2: _1), |
124 | a2: catch_exception<A1>( |
125 | a: var(t&: ecount)++ |
126 | ), |
127 | a3: catch_exception<A2>( |
128 | a: var(t&: ecount)++ |
129 | ), |
130 | a4: catch_exception<A3>( |
131 | a: var(t&: ecount)++ |
132 | ) |
133 | )(i); |
134 | } |
135 | BOOST_CHECK(ecount == 3); |
136 | |
137 | ecount = 0; |
138 | for(int i=1; i<=4; i++) |
139 | { |
140 | try_catch( |
141 | a1: bind(a1&: throw_AX, a2: _1), |
142 | a2: catch_exception<A1>( |
143 | a: var(t&: ecount)++ |
144 | ), |
145 | a3: catch_exception<A2>( |
146 | a: var(t&: ecount)++ |
147 | ), |
148 | a4: catch_exception<A3>( |
149 | a: var(t&: ecount)++ |
150 | ), |
151 | a5: catch_exception<A4>( |
152 | a: var(t&: ecount)++ |
153 | ) |
154 | )(i); |
155 | } |
156 | BOOST_CHECK(ecount == 4); |
157 | |
158 | ecount = 0; |
159 | for(int i=1; i<=5; i++) |
160 | { |
161 | try_catch( |
162 | a1: bind(a1&: throw_AX, a2: _1), |
163 | a2: catch_exception<A1>( |
164 | a: var(t&: ecount)++ |
165 | ), |
166 | a3: catch_exception<A2>( |
167 | a: var(t&: ecount)++ |
168 | ), |
169 | a4: catch_exception<A3>( |
170 | a: var(t&: ecount)++ |
171 | ), |
172 | a5: catch_exception<A4>( |
173 | a: var(t&: ecount)++ |
174 | ), |
175 | a6: catch_exception<A5>( |
176 | a: var(t&: ecount)++ |
177 | ) |
178 | )(i); |
179 | } |
180 | BOOST_CHECK(ecount == 5); |
181 | |
182 | ecount = 0; |
183 | for(int i=1; i<=6; i++) |
184 | { |
185 | try_catch( |
186 | a1: bind(a1&: throw_AX, a2: _1), |
187 | a2: catch_exception<A1>( |
188 | a: var(t&: ecount)++ |
189 | ), |
190 | a3: catch_exception<A2>( |
191 | a: var(t&: ecount)++ |
192 | ), |
193 | a4: catch_exception<A3>( |
194 | a: var(t&: ecount)++ |
195 | ), |
196 | a5: catch_exception<A4>( |
197 | a: var(t&: ecount)++ |
198 | ), |
199 | a6: catch_exception<A5>( |
200 | a: var(t&: ecount)++ |
201 | ), |
202 | a7: catch_exception<A6>( |
203 | a: var(t&: ecount)++ |
204 | ) |
205 | )(i); |
206 | } |
207 | BOOST_CHECK(ecount == 6); |
208 | |
209 | ecount = 0; |
210 | for(int i=1; i<=7; i++) |
211 | { |
212 | try_catch( |
213 | a1: bind(a1&: throw_AX, a2: _1), |
214 | a2: catch_exception<A1>( |
215 | a: var(t&: ecount)++ |
216 | ), |
217 | a3: catch_exception<A2>( |
218 | a: var(t&: ecount)++ |
219 | ), |
220 | a4: catch_exception<A3>( |
221 | a: var(t&: ecount)++ |
222 | ), |
223 | a5: catch_exception<A4>( |
224 | a: var(t&: ecount)++ |
225 | ), |
226 | a6: catch_exception<A5>( |
227 | a: var(t&: ecount)++ |
228 | ), |
229 | a7: catch_exception<A6>( |
230 | a: var(t&: ecount)++ |
231 | ), |
232 | a8: catch_exception<A7>( |
233 | a: var(t&: ecount)++ |
234 | ) |
235 | )(i); |
236 | } |
237 | BOOST_CHECK(ecount == 7); |
238 | |
239 | ecount = 0; |
240 | for(int i=1; i<=8; i++) |
241 | { |
242 | try_catch( |
243 | a1: bind(a1&: throw_AX, a2: _1), |
244 | a2: catch_exception<A1>( |
245 | a: var(t&: ecount)++ |
246 | ), |
247 | a3: catch_exception<A2>( |
248 | a: var(t&: ecount)++ |
249 | ), |
250 | a4: catch_exception<A3>( |
251 | a: var(t&: ecount)++ |
252 | ), |
253 | a5: catch_exception<A4>( |
254 | a: var(t&: ecount)++ |
255 | ), |
256 | a6: catch_exception<A5>( |
257 | a: var(t&: ecount)++ |
258 | ), |
259 | a7: catch_exception<A6>( |
260 | a: var(t&: ecount)++ |
261 | ), |
262 | a8: catch_exception<A7>( |
263 | a: var(t&: ecount)++ |
264 | ), |
265 | a9: catch_exception<A8>( |
266 | a: var(t&: ecount)++ |
267 | ) |
268 | )(i); |
269 | } |
270 | BOOST_CHECK(ecount == 8); |
271 | |
272 | ecount = 0; |
273 | for(int i=1; i<=9; i++) |
274 | { |
275 | try_catch( |
276 | a1: bind(a1&: throw_AX, a2: _1), |
277 | a2: catch_exception<A1>( |
278 | a: var(t&: ecount)++ |
279 | ), |
280 | a3: catch_exception<A2>( |
281 | a: var(t&: ecount)++ |
282 | ), |
283 | a4: catch_exception<A3>( |
284 | a: var(t&: ecount)++ |
285 | ), |
286 | a5: catch_exception<A4>( |
287 | a: var(t&: ecount)++ |
288 | ), |
289 | a6: catch_exception<A5>( |
290 | a: var(t&: ecount)++ |
291 | ), |
292 | a7: catch_exception<A6>( |
293 | a: var(t&: ecount)++ |
294 | ), |
295 | a8: catch_exception<A7>( |
296 | a: var(t&: ecount)++ |
297 | ), |
298 | a9: catch_exception<A8>( |
299 | a: var(t&: ecount)++ |
300 | ), |
301 | a10: catch_exception<A9>( |
302 | a: var(t&: ecount)++ |
303 | ) |
304 | )(i); |
305 | } |
306 | BOOST_CHECK(ecount == 9); |
307 | |
308 | |
309 | // with catch(...) blocks |
310 | |
311 | ecount = 0; |
312 | for(int i=1; i<=1; i++) |
313 | { |
314 | try_catch( |
315 | a1: bind(a1&: throw_AX, a2: _1), |
316 | a2: catch_all( |
317 | a: var(t&: ecount)++ |
318 | ) |
319 | )(i); |
320 | } |
321 | BOOST_CHECK(ecount == 1); |
322 | |
323 | ecount = 0; |
324 | for(int i=1; i<=2; i++) |
325 | { |
326 | try_catch( |
327 | a1: bind(a1&: throw_AX, a2: _1), |
328 | a2: catch_exception<A1>( |
329 | a: var(t&: ecount)++ |
330 | ), |
331 | a3: catch_all( |
332 | a: var(t&: ecount)++ |
333 | ) |
334 | )(i); |
335 | } |
336 | BOOST_CHECK(ecount == 2); |
337 | |
338 | ecount = 0; |
339 | for(int i=1; i<=3; i++) |
340 | { |
341 | try_catch( |
342 | a1: bind(a1&: throw_AX, a2: _1), |
343 | a2: catch_exception<A1>( |
344 | a: var(t&: ecount)++ |
345 | ), |
346 | a3: catch_exception<A2>( |
347 | a: var(t&: ecount)++ |
348 | ), |
349 | a4: catch_all( |
350 | a: var(t&: ecount)++ |
351 | ) |
352 | )(i); |
353 | } |
354 | BOOST_CHECK(ecount == 3); |
355 | |
356 | ecount = 0; |
357 | for(int i=1; i<=4; i++) |
358 | { |
359 | try_catch( |
360 | a1: bind(a1&: throw_AX, a2: _1), |
361 | a2: catch_exception<A1>( |
362 | a: var(t&: ecount)++ |
363 | ), |
364 | a3: catch_exception<A2>( |
365 | a: var(t&: ecount)++ |
366 | ), |
367 | a4: catch_exception<A3>( |
368 | a: var(t&: ecount)++ |
369 | ), |
370 | a5: catch_all( |
371 | a: var(t&: ecount)++ |
372 | ) |
373 | )(i); |
374 | } |
375 | BOOST_CHECK(ecount == 4); |
376 | |
377 | ecount = 0; |
378 | for(int i=1; i<=5; i++) |
379 | { |
380 | try_catch( |
381 | a1: bind(a1&: throw_AX, a2: _1), |
382 | a2: catch_exception<A1>( |
383 | a: var(t&: ecount)++ |
384 | ), |
385 | a3: catch_exception<A2>( |
386 | a: var(t&: ecount)++ |
387 | ), |
388 | a4: catch_exception<A3>( |
389 | a: var(t&: ecount)++ |
390 | ), |
391 | a5: catch_exception<A4>( |
392 | a: var(t&: ecount)++ |
393 | ), |
394 | a6: catch_all( |
395 | a: var(t&: ecount)++ |
396 | ) |
397 | )(i); |
398 | } |
399 | BOOST_CHECK(ecount == 5); |
400 | |
401 | ecount = 0; |
402 | for(int i=1; i<=6; i++) |
403 | { |
404 | try_catch( |
405 | a1: bind(a1&: throw_AX, a2: _1), |
406 | a2: catch_exception<A1>( |
407 | a: var(t&: ecount)++ |
408 | ), |
409 | a3: catch_exception<A2>( |
410 | a: var(t&: ecount)++ |
411 | ), |
412 | a4: catch_exception<A3>( |
413 | a: var(t&: ecount)++ |
414 | ), |
415 | a5: catch_exception<A4>( |
416 | a: var(t&: ecount)++ |
417 | ), |
418 | a6: catch_exception<A5>( |
419 | a: var(t&: ecount)++ |
420 | ), |
421 | a7: catch_all( |
422 | a: var(t&: ecount)++ |
423 | ) |
424 | )(i); |
425 | } |
426 | BOOST_CHECK(ecount == 6); |
427 | |
428 | ecount = 0; |
429 | for(int i=1; i<=7; i++) |
430 | { |
431 | try_catch( |
432 | a1: bind(a1&: throw_AX, a2: _1), |
433 | a2: catch_exception<A1>( |
434 | a: var(t&: ecount)++ |
435 | ), |
436 | a3: catch_exception<A2>( |
437 | a: var(t&: ecount)++ |
438 | ), |
439 | a4: catch_exception<A3>( |
440 | a: var(t&: ecount)++ |
441 | ), |
442 | a5: catch_exception<A4>( |
443 | a: var(t&: ecount)++ |
444 | ), |
445 | a6: catch_exception<A5>( |
446 | a: var(t&: ecount)++ |
447 | ), |
448 | a7: catch_exception<A6>( |
449 | a: var(t&: ecount)++ |
450 | ), |
451 | a8: catch_all( |
452 | a: var(t&: ecount)++ |
453 | ) |
454 | )(i); |
455 | } |
456 | BOOST_CHECK(ecount == 7); |
457 | |
458 | ecount = 0; |
459 | for(int i=1; i<=8; i++) |
460 | { |
461 | try_catch( |
462 | a1: bind(a1&: throw_AX, a2: _1), |
463 | a2: catch_exception<A1>( |
464 | a: var(t&: ecount)++ |
465 | ), |
466 | a3: catch_exception<A2>( |
467 | a: var(t&: ecount)++ |
468 | ), |
469 | a4: catch_exception<A3>( |
470 | a: var(t&: ecount)++ |
471 | ), |
472 | a5: catch_exception<A4>( |
473 | a: var(t&: ecount)++ |
474 | ), |
475 | a6: catch_exception<A5>( |
476 | a: var(t&: ecount)++ |
477 | ), |
478 | a7: catch_exception<A6>( |
479 | a: var(t&: ecount)++ |
480 | ), |
481 | a8: catch_exception<A7>( |
482 | a: var(t&: ecount)++ |
483 | ), |
484 | a9: catch_all( |
485 | a: var(t&: ecount)++ |
486 | ) |
487 | )(i); |
488 | } |
489 | BOOST_CHECK(ecount == 8); |
490 | |
491 | ecount = 0; |
492 | for(int i=1; i<=9; i++) |
493 | { |
494 | try_catch( |
495 | a1: bind(a1&: throw_AX, a2: _1), |
496 | a2: catch_exception<A1>( |
497 | a: var(t&: ecount)++ |
498 | ), |
499 | a3: catch_exception<A2>( |
500 | a: var(t&: ecount)++ |
501 | ), |
502 | a4: catch_exception<A3>( |
503 | a: var(t&: ecount)++ |
504 | ), |
505 | a5: catch_exception<A4>( |
506 | a: var(t&: ecount)++ |
507 | ), |
508 | a6: catch_exception<A5>( |
509 | a: var(t&: ecount)++ |
510 | ), |
511 | a7: catch_exception<A6>( |
512 | a: var(t&: ecount)++ |
513 | ), |
514 | a8: catch_exception<A7>( |
515 | a: var(t&: ecount)++ |
516 | ), |
517 | a9: catch_exception<A8>( |
518 | a: var(t&: ecount)++ |
519 | ), |
520 | a10: catch_all( |
521 | a: var(t&: ecount)++ |
522 | ) |
523 | )(i); |
524 | } |
525 | BOOST_CHECK(ecount == 9); |
526 | } |
527 | |
528 | void test_empty_catch_blocks() { |
529 | try_catch( |
530 | a1: bind(a1&: throw_AX, a2: _1), |
531 | a2: catch_exception<A1>() |
532 | )(make_const(t: 1)); |
533 | |
534 | try_catch( |
535 | a1: bind(a1&: throw_AX, a2: _1), |
536 | a2: catch_all() |
537 | )(make_const(t: 1)); |
538 | |
539 | } |
540 | |
541 | |
542 | void return_type_matching() { |
543 | |
544 | // Rules for return types of the lambda functors in try and catch parts: |
545 | // 1. The try part dictates the return type of the whole |
546 | // try_catch lambda functor |
547 | // 2. If return type of try part is void, catch parts can return anything, |
548 | // but the return types are ignored |
549 | // 3. If the return type of the try part is A, then each catch return type |
550 | // must be implicitly convertible to A, or then it must throw for sure |
551 | |
552 | |
553 | int i = 1; |
554 | |
555 | BOOST_CHECK( |
556 | |
557 | try_catch( |
558 | _1 + 1, |
559 | catch_exception<int>((&_1, rethrow())), // no match, but ok since throws |
560 | catch_exception<char>(_e) // ok, char convertible to int |
561 | )(i) |
562 | |
563 | == 2 |
564 | ); |
565 | |
566 | // note that while e.g. char is convertible to int, it is not convertible |
567 | // to int&, (some lambda functors return references) |
568 | |
569 | // try_catch( |
570 | // _1 += 1, |
571 | // catch_exception<char>(_e) // NOT ok, char not convertible to int& |
572 | // )(i); |
573 | |
574 | // if you don't care about the return type, you can use make_void |
575 | try_catch( |
576 | a1: make_void(a1: _1 += 1), |
577 | a2: catch_exception<char>(a: _e) // since try is void, catch can return anything |
578 | )(i); |
579 | BOOST_CHECK(i == 2); |
580 | |
581 | try_catch( |
582 | a1: (_1 += 1, throw_exception(a1: 'a')), |
583 | a2: catch_exception<char>(a: _e) // since try throws, it is void, |
584 | // so catch can return anything |
585 | )(i); |
586 | BOOST_CHECK(i == 3); |
587 | |
588 | char a = 'a'; |
589 | try_catch( |
590 | a1: try_catch( |
591 | a1: throw_exception(a1: 1), |
592 | a2: catch_exception<int>(a: throw_exception(a1: 'b')) |
593 | ), |
594 | a2: catch_exception<char>( a: _1 = _e ) |
595 | )(a); |
596 | BOOST_CHECK(a == 'b'); |
597 | } |
598 | |
599 | int main() { |
600 | |
601 | try |
602 | { |
603 | test_different_number_of_catch_blocks(); |
604 | return_type_matching(); |
605 | test_empty_catch_blocks(); |
606 | } |
607 | catch (int) |
608 | { |
609 | BOOST_CHECK(false); |
610 | } |
611 | catch(...) |
612 | { |
613 | BOOST_CHECK(false); |
614 | } |
615 | |
616 | |
617 | return boost::report_errors(); |
618 | } |
619 | |