// -- exception_test.cpp -- The Boost Lambda Library ------------------ // // Copyright (C) 2000-2003 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) // Copyright (C) 2000-2003 Gary Powell (powellg@amazon.com) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // For more information, see www.boost.org // ----------------------------------------------------------------------- #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&) {} 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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(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_CHECK(ecount == 9); } void test_empty_catch_blocks() { try_catch( bind(throw_AX, _1), catch_exception() )(make_const(1)); try_catch( bind(throw_AX, _1), catch_all() )(make_const(1)); } 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_CHECK( 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_CHECK(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_CHECK(i == 3); char a = 'a'; try_catch( try_catch( throw_exception(1), catch_exception(throw_exception('b')) ), catch_exception( _1 = _e ) )(a); BOOST_CHECK(a == 'b'); } int test_main(int, char *[]) { try { test_different_number_of_catch_blocks(); return_type_matching(); test_empty_catch_blocks(); } catch (int) { BOOST_CHECK(false); } catch(...) { BOOST_CHECK(false); } return EXIT_SUCCESS; }