7648a7adf1
[SVN r51617]
622 lines
11 KiB
C++
622 lines
11 KiB
C++
// -- 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 <boost/test/minimal.hpp> // see "Header Implementation Option"
|
|
|
|
#include "boost/lambda/lambda.hpp"
|
|
|
|
#include "boost/lambda/exceptions.hpp"
|
|
|
|
#include "boost/lambda/bind.hpp"
|
|
|
|
#include<iostream>
|
|
#include<algorithm>
|
|
#include <cstdlib>
|
|
|
|
#include <iostream>
|
|
|
|
using namespace boost::lambda;
|
|
using namespace std;
|
|
|
|
// to prevent unused variables warnings
|
|
template <class T> 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<int>(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<A1>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 1);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=2; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 2);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=3; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 3);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=4; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 4);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=5; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 5);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=6; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 6);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=7; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A7>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 7);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=8; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A7>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A8>(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 8);
|
|
|
|
ecount = 0;
|
|
for(int i=1; i<=9; i++)
|
|
{
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A7>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A8>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A9>(
|
|
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<A1>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A7>(
|
|
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<A1>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A2>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A3>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A4>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A5>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A6>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A7>(
|
|
var(ecount)++
|
|
),
|
|
catch_exception<A8>(
|
|
var(ecount)++
|
|
),
|
|
catch_all(
|
|
var(ecount)++
|
|
)
|
|
)(i);
|
|
}
|
|
BOOST_CHECK(ecount == 9);
|
|
}
|
|
|
|
void test_empty_catch_blocks() {
|
|
try_catch(
|
|
bind(throw_AX, _1),
|
|
catch_exception<A1>()
|
|
)(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<int>((&_1, rethrow())), // no match, but ok since throws
|
|
catch_exception<char>(_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<char>(_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<char>(_e) // since try is void, catch can return anything
|
|
)(i);
|
|
BOOST_CHECK(i == 2);
|
|
|
|
try_catch(
|
|
(_1 += 1, throw_exception('a')),
|
|
catch_exception<char>(_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<int>(throw_exception('b'))
|
|
),
|
|
catch_exception<char>( _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;
|
|
}
|
|
|
|
|
|
|
|
|