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
29using namespace boost::lambda;
30using namespace std;
31
32// to prevent unused variables warnings
33template <class T> void dummy(const T&) {}
34
35void 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
60class A1 {};
61class A2 {};
62class A3 {};
63class A4 {};
64class A5 {};
65class A6 {};
66class A7 {};
67class A8 {};
68class A9 {};
69
70void 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
85void 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
528void 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
542void 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
599int 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

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