#define BOOST_INCLUDE_MAIN // for testing, include rather than link #include // see "Header Implementation Option" #include "boost/lambda/lambda.hpp" #include "boost/lambda/exceptions.hpp" #include "boost/lambda/bind.hpp" #include #include #include #include using namespace boost::lambda; using namespace std; // to prevent unused variables warnings template void dummy(const T& t) {} void erroneous_exception_related_lambda_expressions() { int i = 0; dummy(i); // Uncommenting any of the below code lines should result in a compile // time error // this should fail (a rethrow binder outside of catch // rethrow()(); // this should fail too for the same reason // try_catch(rethrow(), catch_all(cout << constant("Howdy")))(); // this fails too (_E outside of catch_exception) // (_1 + _2 + _E)(i, i, i); // and this (_E outside of catch_exception) // try_catch( throw_exception(1), catch_all(cout << _E)); // and this (_3 in catch_exception // try_catch( throw_exception(1), catch_exception(cout << _3)); } class A1 {}; class A2 {}; class A3 {}; class A4 {}; class A5 {}; class A6 {}; class A7 {}; class A8 {}; class A9 {}; void throw_AX(int j) { int i = j; switch(i) { case 1: throw A1(); case 2: throw A2(); case 3: throw A3(); case 4: throw A4(); case 5: throw A5(); case 6: throw A6(); case 7: throw A7(); case 8: throw A8(); case 9: throw A9(); } } void test_different_number_of_catch_blocks() { int ecount; // no catch(...) cases ecount = 0; for(int i=1; i<=1; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 1); ecount = 0; for(int i=1; i<=2; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 2); ecount = 0; for(int i=1; i<=3; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 3); ecount = 0; for(int i=1; i<=4; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 4); ecount = 0; for(int i=1; i<=5; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 5); ecount = 0; for(int i=1; i<=6; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 6); ecount = 0; for(int i=1; i<=7; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 7); ecount = 0; for(int i=1; i<=8; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 8); ecount = 0; for(int i=1; i<=9; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 9); // with catch(...) blocks ecount = 0; for(int i=1; i<=1; i++) { try_catch( bind(throw_AX, _1), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 1); ecount = 0; for(int i=1; i<=2; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 2); ecount = 0; for(int i=1; i<=3; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 3); ecount = 0; for(int i=1; i<=4; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 4); ecount = 0; for(int i=1; i<=5; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 5); ecount = 0; for(int i=1; i<=6; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 6); ecount = 0; for(int i=1; i<=7; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 7); ecount = 0; for(int i=1; i<=8; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 8); ecount = 0; for(int i=1; i<=9; i++) { try_catch( bind(throw_AX, _1), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_exception( var(ecount)++ ), catch_all( var(ecount)++ ) )(i); } BOOST_TEST(ecount == 9); } void return_type_matching() { // Rules for return types of the lambda functors in try and catch parts: // 1. The try part dictates the return type of the whole // try_catch lambda functor // 2. If return type of try part is void, catch parts can return anything, // but the return types are ignored // 3. If the return type of the try part is A, then each catch return type // must be implicitly convertible to A, or then it must throw for sure int i = 1; BOOST_TEST( try_catch( _1 + 1, catch_exception((&_1, rethrow())), // no match, but ok since throws catch_exception(_E) // ok, char convertible to int )(i) == 2 ); // note that while e.g. char is convertible to int, it is not convertible // to int&, (some lambda functors return references) // try_catch( // _1 += 1, // catch_exception(_E) // NOT ok, char not convertible to int& // )(i); // if you don't care about the return type, you can use make_void try_catch( make_void(_1 += 1), catch_exception(_E) // since try is void, catch can return anything )(i); BOOST_TEST(i == 2); try_catch( (_1 += 1, throw_exception('a')), catch_exception(_E) // since try throws, it is void, // so catch can return anything )(i); BOOST_TEST(i == 3); char a = 'a'; try_catch( try_catch( throw_exception(1), catch_exception(throw_exception('b')) ), catch_exception( _1 = _E ) )(a); BOOST_TEST(a == 'b'); } int test_main(int, char *[]) { try { test_different_number_of_catch_blocks(); return_type_matching(); } catch (int x) { BOOST_TEST(false); } catch(...) { BOOST_TEST(false); } return EXIT_SUCCESS; } // cout << "Before make void call. i ="<< i << "\n"; // (make_void(free1 += 3))(i); // cout << "After make void call, should be += 3 i = " << i << "\n"; // int j =0; // var_type::type vj(var(j)); // (make_void(for_loop(vj = 0, vj < free1, ++vj, cout << vj << "\n")))(i); // try_catch( make_void(free1 += 3 + free2), // catch_exception( cout << constant("Should work: ") << free1 + free2 << "\n" ) // ) // (i, i); // try_catch( make_void(free1 += 3), // catch_exception( cout << constant("Should work: ") << free1 + free2 << "\n" ) // ) // (i, i); // try_catch( throw_exception(1), // catch_exception( // throw_exception(2) ) // ) // (); // try_catch( throw_exception(1), // catch_exception( // ((cout << constant("caught int: ") << free1 + free2 << "\n") // ,throw_exception(2) ) // ), // catch_all( // ((cout << constant("catch all: ") << free1 + free2 << "\n") // ,rethrow()) // ) // )(i,i); // // try_catch which returns (10 is added, so that the try return type is int // cout << "\n -------------- \n" << // try_catch( (throw_exception(5), 10), // catch_exception( free1 + free2 + freeE ) // returns int // ) // (i, i) << "\n";