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 bind(throw_AX, _1),
96 catch_exception<A1>(
97 var(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 bind(throw_AX, _1),
108 catch_exception<A1>(
109 var(ecount)++
110 ),
111 catch_exception<A2>(
112 var(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 bind(throw_AX, _1),
123 catch_exception<A1>(
124 var(ecount)++
125 ),
126 catch_exception<A2>(
127 var(ecount)++
128 ),
129 catch_exception<A3>(
130 var(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 bind(throw_AX, _1),
141 catch_exception<A1>(
142 var(ecount)++
143 ),
144 catch_exception<A2>(
145 var(ecount)++
146 ),
147 catch_exception<A3>(
148 var(ecount)++
149 ),
150 catch_exception<A4>(
151 var(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 bind(throw_AX, _1),
162 catch_exception<A1>(
163 var(ecount)++
164 ),
165 catch_exception<A2>(
166 var(ecount)++
167 ),
168 catch_exception<A3>(
169 var(ecount)++
170 ),
171 catch_exception<A4>(
172 var(ecount)++
173 ),
174 catch_exception<A5>(
175 var(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 bind(throw_AX, _1),
186 catch_exception<A1>(
187 var(ecount)++
188 ),
189 catch_exception<A2>(
190 var(ecount)++
191 ),
192 catch_exception<A3>(
193 var(ecount)++
194 ),
195 catch_exception<A4>(
196 var(ecount)++
197 ),
198 catch_exception<A5>(
199 var(ecount)++
200 ),
201 catch_exception<A6>(
202 var(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 bind(throw_AX, _1),
213 catch_exception<A1>(
214 var(ecount)++
215 ),
216 catch_exception<A2>(
217 var(ecount)++
218 ),
219 catch_exception<A3>(
220 var(ecount)++
221 ),
222 catch_exception<A4>(
223 var(ecount)++
224 ),
225 catch_exception<A5>(
226 var(ecount)++
227 ),
228 catch_exception<A6>(
229 var(ecount)++
230 ),
231 catch_exception<A7>(
232 var(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 bind(throw_AX, _1),
243 catch_exception<A1>(
244 var(ecount)++
245 ),
246 catch_exception<A2>(
247 var(ecount)++
248 ),
249 catch_exception<A3>(
250 var(ecount)++
251 ),
252 catch_exception<A4>(
253 var(ecount)++
254 ),
255 catch_exception<A5>(
256 var(ecount)++
257 ),
258 catch_exception<A6>(
259 var(ecount)++
260 ),
261 catch_exception<A7>(
262 var(ecount)++
263 ),
264 catch_exception<A8>(
265 var(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 bind(throw_AX, _1),
276 catch_exception<A1>(
277 var(ecount)++
278 ),
279 catch_exception<A2>(
280 var(ecount)++
281 ),
282 catch_exception<A3>(
283 var(ecount)++
284 ),
285 catch_exception<A4>(
286 var(ecount)++
287 ),
288 catch_exception<A5>(
289 var(ecount)++
290 ),
291 catch_exception<A6>(
292 var(ecount)++
293 ),
294 catch_exception<A7>(
295 var(ecount)++
296 ),
297 catch_exception<A8>(
298 var(ecount)++
299 ),
300 catch_exception<A9>(
301 var(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 bind(throw_AX, _1),
315 catch_all(
316 var(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 bind(throw_AX, _1),
327 catch_exception<A1>(
328 var(ecount)++
329 ),
330 catch_all(
331 var(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 bind(throw_AX, _1),
342 catch_exception<A1>(
343 var(ecount)++
344 ),
345 catch_exception<A2>(
346 var(ecount)++
347 ),
348 catch_all(
349 var(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 bind(throw_AX, _1),
360 catch_exception<A1>(
361 var(ecount)++
362 ),
363 catch_exception<A2>(
364 var(ecount)++
365 ),
366 catch_exception<A3>(
367 var(ecount)++
368 ),
369 catch_all(
370 var(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 bind(throw_AX, _1),
381 catch_exception<A1>(
382 var(ecount)++
383 ),
384 catch_exception<A2>(
385 var(ecount)++
386 ),
387 catch_exception<A3>(
388 var(ecount)++
389 ),
390 catch_exception<A4>(
391 var(ecount)++
392 ),
393 catch_all(
394 var(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 bind(throw_AX, _1),
405 catch_exception<A1>(
406 var(ecount)++
407 ),
408 catch_exception<A2>(
409 var(ecount)++
410 ),
411 catch_exception<A3>(
412 var(ecount)++
413 ),
414 catch_exception<A4>(
415 var(ecount)++
416 ),
417 catch_exception<A5>(
418 var(ecount)++
419 ),
420 catch_all(
421 var(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 bind(throw_AX, _1),
432 catch_exception<A1>(
433 var(ecount)++
434 ),
435 catch_exception<A2>(
436 var(ecount)++
437 ),
438 catch_exception<A3>(
439 var(ecount)++
440 ),
441 catch_exception<A4>(
442 var(ecount)++
443 ),
444 catch_exception<A5>(
445 var(ecount)++
446 ),
447 catch_exception<A6>(
448 var(ecount)++
449 ),
450 catch_all(
451 var(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 bind(throw_AX, _1),
462 catch_exception<A1>(
463 var(ecount)++
464 ),
465 catch_exception<A2>(
466 var(ecount)++
467 ),
468 catch_exception<A3>(
469 var(ecount)++
470 ),
471 catch_exception<A4>(
472 var(ecount)++
473 ),
474 catch_exception<A5>(
475 var(ecount)++
476 ),
477 catch_exception<A6>(
478 var(ecount)++
479 ),
480 catch_exception<A7>(
481 var(ecount)++
482 ),
483 catch_all(
484 var(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 bind(throw_AX, _1),
495 catch_exception<A1>(
496 var(ecount)++
497 ),
498 catch_exception<A2>(
499 var(ecount)++
500 ),
501 catch_exception<A3>(
502 var(ecount)++
503 ),
504 catch_exception<A4>(
505 var(ecount)++
506 ),
507 catch_exception<A5>(
508 var(ecount)++
509 ),
510 catch_exception<A6>(
511 var(ecount)++
512 ),
513 catch_exception<A7>(
514 var(ecount)++
515 ),
516 catch_exception<A8>(
517 var(ecount)++
518 ),
519 catch_all(
520 var(ecount)++
521 )
522 )(i);
523 }
524 BOOST_CHECK(ecount == 9);
525}
526
527void test_empty_catch_blocks() {
528 try_catch(
529 bind(throw_AX, _1),
530 catch_exception<A1>()
531 )(make_const(1));
532
533 try_catch(
534 bind(throw_AX, _1),
535 catch_all()
536 )(make_const(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 make_void(_1 += 1),
576 catch_exception<char>(_e) // since try is void, catch can return anything
577 )(i);
578 BOOST_CHECK(i == 2);
579
580 try_catch(
581 (_1 += 1, throw_exception('a')),
582 catch_exception<char>(_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 try_catch(
590 throw_exception(1),
591 catch_exception<int>(throw_exception('b'))
592 ),
593 catch_exception<char>( _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