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

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