decoupled boost/exception/exception.hpp from boost/exception/detail/type_info.hpp

diagnostic_information improvements
documentation update

[SVN r48469]
This commit is contained in:
Emil Dotchevski
2008-08-30 02:57:12 +00:00
parent e1aba12621
commit 9dd2d64304
15 changed files with 3062 additions and 2888 deletions

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ error: //Base for all exception objects we throw.
char const * char const *
what() const throw() what() const throw()
{ {
return boost::exception::diagnostic_information(); return "example_io error";
} }
protected: protected:
@ -170,7 +170,7 @@ dump_all_info( boost::exception const & x )
dump_file_info(x); dump_file_info(x);
dump_clib_info(x); dump_clib_info(x);
std::cout << "\nOutput from diagnostic_information():\n"; std::cout << "\nOutput from diagnostic_information():\n";
std::cout << x.diagnostic_information(); std::cout << diagnostic_information(x);
} }
int int

View File

@ -1,47 +0,0 @@
//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc.
//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)
#ifndef UUID_B9A8291074CA11DD94BFC77156D89593
#define UUID_B9A8291074CA11DD94BFC77156D89593
#include <boost/exception/exception.hpp>
namespace
boost
{
namespace
exception_detail
{
#ifdef BOOST_NO_RTTI
template <class T>
exception const *
get_boost_exception( T const * )
{
try
{
throw;
}
catch(
exception & x )
{
return &x;
}
catch(...)
{
return 0;
}
}
#else
template <class T>
exception const *
get_boost_exception( T const * x )
{
return dynamic_cast<exception const *>(x);
}
#endif
}
}
#endif

View File

@ -12,10 +12,10 @@
namespace namespace
boost boost
{ {
template <class ErrorInfoTag> template <class T>
inline inline
char const * char const *
error_info_value() type_name()
{ {
return BOOST_CURRENT_FUNCTION; return BOOST_CURRENT_FUNCTION;
} }
@ -23,40 +23,99 @@ boost
namespace namespace
exception_detail exception_detail
{ {
typedef detail::sp_typeinfo type_info_;
#ifdef BOOST_NO_TYPEID #ifdef BOOST_NO_TYPEID
typedef type_info_ type_info_wrapper;
#else
struct struct
type_info_wrapper type_info_
{ {
type_info_ const * type; detail::sp_typeinfo type_;
char const * name_;
explicit explicit
type_info_wrapper( type_info_ const & t ): type_info_( detail::sp_typeinfo type, char const * name ):
type(&t) type_(type),
name_(name)
{ {
} }
friend
bool bool
operator<( type_info_wrapper const & b ) const operator==( type_info_ const & a, type_info_ const & b )
{ {
return 0!=(type->before(*b.type)); return a.type_==b.type_;
}
friend
bool
operator!=( type_info_ const & a, type_info_ const & b )
{
return !(a==b);
}
friend
bool
operator<( type_info_ const & a, type_info_ const & b )
{
return a.type_<b.type_;
}
char const *
name() const
{
return name_;
}
};
#else
struct
type_info_
{
detail::sp_typeinfo const * type_;
explicit
type_info_( detail::sp_typeinfo const & type ):
type_(&type)
{
}
type_info_( detail::sp_typeinfo const & type, char const * ):
type_(&type)
{
}
friend
bool
operator==( type_info_ const & a, type_info_ const & b )
{
return (*a.type_)==(*b.type_);
}
friend
bool
operator!=( type_info_ const & a, type_info_ const & b )
{
return !(a==b);
}
friend
bool
operator<( type_info_ const & a, type_info_ const & b )
{
return 0!=(a.type_->before(*b.type_));
}
char const *
name() const
{
return type_->name();
} }
}; };
#endif #endif
template <class ErrorInfoTag>
inline
char const *
type_name()
{
return error_info_value<ErrorInfoTag>();
}
} }
} }
#define BOOST_EXCEPTION_STATIC_TYPEID(T) BOOST_SP_TYPEID(T) #define BOOST_EXCEPTION_STATIC_TYPEID(T) ::boost::exception_detail::type_info_(BOOST_SP_TYPEID(T),::boost::type_name<T>())
#ifndef BOOST_NO_RTTI
#define BOOST_EXCEPTION_DYNAMIC_TYPEID(x) ::boost::exception_detail::type_info_(typeid(x))
#endif
#endif #endif

View File

@ -6,27 +6,87 @@
#ifndef UUID_0552D49838DD11DD90146B8956D89593 #ifndef UUID_0552D49838DD11DD90146B8956D89593
#define UUID_0552D49838DD11DD90146B8956D89593 #define UUID_0552D49838DD11DD90146B8956D89593
#include <boost/exception/detail/get_boost_exception.hpp> #include <boost/exception/exception.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <exception> #include <exception>
#include <string> #include <string>
namespace namespace
boost boost
{ {
namespace
exception_detail
{
template <class T>
std::string
std_exception_diagnostic_information( std::exception const * x, T const & )
{
if( char const * s=x->what() )
if( *s )
return std::string("std::exception::what(): ")+s;
return std::string();
}
template <class T>
std::string
std_exception_diagnostic_information( void const *, T const & e )
{
#ifndef BOOST_NO_RTTI
if( std::exception const * x=dynamic_cast<std::exception const *>(&e) )
return std_exception_diagnostic_information(x,e);
else
#endif
return std::string();
}
template <class T>
std::string
boost_exception_diagnostic_information( boost::exception const * x, T const & )
{
if( char const * s=x->diagnostic_information() )
if( *s )
return std::string("boost::exception::diagnostic_information():\n")+s;
return std::string();
}
template <class T>
std::string
boost_exception_diagnostic_information( void const *, T const & e )
{
#ifndef BOOST_NO_RTTI
if( exception const * x=dynamic_cast<exception const *>(&e) )
return boost_exception_diagnostic_information(x,e);
else
#endif
return std::string();
}
}
template <class T>
inline inline
std::string std::string
diagnostic_information( std::exception const & x ) diagnostic_information( T const & x )
{ {
if( exception const * be = exception_detail::get_boost_exception(&x) ) std::string di=
return be->diagnostic_information();
else
return std::string("[ what: ") + x.what() + ", type: "
#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID) #if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID)
"Unknown type deriving from std::exception" std::string("Static exception type: ")+BOOST_EXCEPTION_STATIC_TYPEID(T)
#else #else
+ typeid(x).name() + std::string("Dynamic exception type: ")+BOOST_EXCEPTION_DYNAMIC_TYPEID(x)
#endif #endif
" ]"; .name();
std::string di1=exception_detail::std_exception_diagnostic_information(&x,x);
if( !di1.empty() )
{
di+='\n';
di+=di1;
}
std::string di2=exception_detail::boost_exception_diagnostic_information(&x,x);
if( !di2.empty() )
{
di+='\n';
di+=di2;
}
return di;
} }
} }

View File

@ -32,12 +32,6 @@ boost
~error_info_injector() throw() ~error_info_injector() throw()
{ {
} }
char const *
diagnostic_information() const throw()
{
return boost::exception::_diagnostic_information(T::what());
}
}; };
struct large_size { char c[256]; }; struct large_size { char c[256]; };

View File

@ -6,11 +6,8 @@
#ifndef UUID_274DA366004E11DCB1DDFE2E56D89593 #ifndef UUID_274DA366004E11DCB1DDFE2E56D89593
#define UUID_274DA366004E11DCB1DDFE2E56D89593 #define UUID_274DA366004E11DCB1DDFE2E56D89593
#include <boost/exception/detail/type_info.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/exception/detail/counted_base.hpp> #include <boost/exception/detail/counted_base.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <typeinfo>
namespace namespace
boost boost
@ -24,12 +21,13 @@ boost
exception_detail exception_detail
{ {
class error_info_base; class error_info_base;
struct type_info_;
struct struct
error_info_container: error_info_container:
public exception_detail::counted_base public exception_detail::counted_base
{ {
virtual char const * diagnostic_information( char const *, char const * ) const = 0; virtual char const * diagnostic_information() const = 0;
virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0; virtual shared_ptr<error_info_base const> get( type_info_ const & ) const = 0;
virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0; virtual void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0;
}; };
@ -37,7 +35,7 @@ boost
template <class ErrorInfo> template <class ErrorInfo>
shared_ptr<typename ErrorInfo::value_type const> get_data( exception const & ); shared_ptr<typename ErrorInfo::value_type const> get_data( exception const & );
void set_data( exception const *, shared_ptr<exception_detail::error_info_base const> const &, exception_detail::type_info_ const & ); void set_data( exception const *, shared_ptr<exception_detail::error_info_base const> const &, type_info_ const & );
} }
class class
@ -49,7 +47,7 @@ boost
char const * char const *
diagnostic_information() const throw() diagnostic_information() const throw()
{ {
return _diagnostic_information(0); return _diagnostic_information();
} }
protected: protected:
@ -63,22 +61,6 @@ boost
{ {
} }
char const *
_diagnostic_information( char const * std_what ) const throw()
{
if( data_ )
try
{
char const * w = data_->diagnostic_information(std_what,dynamic_type_name());
BOOST_ASSERT(w!=0);
return w;
}
catch(...)
{
}
return std_what ? std_what : dynamic_type_name();
}
#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) #if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) )
//Force class exception to be abstract. //Force class exception to be abstract.
//Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected. //Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected.
@ -92,6 +74,22 @@ boost
} }
#endif #endif
char const *
_diagnostic_information() const throw()
{
if( data_ )
try
{
char const * w = data_->diagnostic_information();
BOOST_ASSERT(w!=0);
return w;
}
catch(...)
{
}
return "";
}
private: private:
friend void exception_detail::set_data( exception const *, shared_ptr<exception_detail::error_info_base const> const &, exception_detail::type_info_ const & ); friend void exception_detail::set_data( exception const *, shared_ptr<exception_detail::error_info_base const> const &, exception_detail::type_info_ const & );
@ -99,18 +97,6 @@ boost
template <class ErrorInfo> template <class ErrorInfo>
friend shared_ptr<typename ErrorInfo::value_type const> exception_detail::get_data( exception const & ); friend shared_ptr<typename ErrorInfo::value_type const> exception_detail::get_data( exception const & );
char const *
dynamic_type_name() const
{
return
#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID)
"Unknown type deriving from boost::exception"
#else
typeid(*this).name()
#endif
;
}
mutable intrusive_ptr<exception_detail::error_info_container> data_; mutable intrusive_ptr<exception_detail::error_info_container> data_;
}; };

View File

@ -6,9 +6,10 @@
#ifndef UUID_1A590226753311DD9E4CCF6156D89593 #ifndef UUID_1A590226753311DD9E4CCF6156D89593
#define UUID_1A590226753311DD9E4CCF6156D89593 #define UUID_1A590226753311DD9E4CCF6156D89593
#include <boost/shared_ptr.hpp> #include <boost/exception/exception.hpp>
#include <boost/exception/detail/get_boost_exception.hpp>
#include <boost/exception/detail/error_info_base.hpp> #include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp>
namespace namespace
boost boost
@ -34,16 +35,26 @@ boost
} }
} }
#ifdef BOOST_NO_RTTI
template <class ErrorInfo>
inline
shared_ptr<typename ErrorInfo::value_type const>
get_error_info( boost::exception const & x )
{
return exception_detail::get_data<ErrorInfo>(x);
}
#else
template <class ErrorInfo,class E> template <class ErrorInfo,class E>
inline inline
shared_ptr<typename ErrorInfo::value_type const> shared_ptr<typename ErrorInfo::value_type const>
get_error_info( E const & some_exception ) get_error_info( E const & some_exception )
{ {
if( exception const * x = exception_detail::get_boost_exception(&some_exception) ) if( exception const * x = dynamic_cast<exception const *>(&some_exception) )
return exception_detail::get_data<ErrorInfo>(*x); return exception_detail::get_data<ErrorInfo>(*x);
else else
return shared_ptr<typename ErrorInfo::value_type const>(); return shared_ptr<typename ErrorInfo::value_type const>();
} }
#endif
} }
#endif #endif

View File

@ -7,9 +7,10 @@
#define UUID_8D22C4CA9CC811DCAA9133D256D89593 #define UUID_8D22C4CA9CC811DCAA9133D256D89593
#include <boost/exception/exception.hpp> #include <boost/exception/exception.hpp>
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/error_info.hpp> #include <boost/exception/error_info.hpp>
#include <boost/exception/to_string_stub.hpp> #include <boost/exception/to_string_stub.hpp>
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <map> #include <map>
@ -50,7 +51,7 @@ boost
char const * char const *
tag_typeid_name() const tag_typeid_name() const
{ {
return exception_detail::type_name<Tag>(); return type_name<Tag>();
} }
std::string std::string
@ -84,19 +85,19 @@ boost
set( shared_ptr<error_info_base const> const & x, type_info_ const & typeid_ ) set( shared_ptr<error_info_base const> const & x, type_info_ const & typeid_ )
{ {
BOOST_ASSERT(x); BOOST_ASSERT(x);
info_[type_info_wrapper(typeid_)] = x; info_[typeid_] = x;
what_.clear(); diagnostic_info_str_.clear();
} }
shared_ptr<error_info_base const> shared_ptr<error_info_base const>
get( type_info_ const & ti ) const get( type_info_ const & ti ) const
{ {
error_info_map::const_iterator i=info_.find(type_info_wrapper(ti)); error_info_map::const_iterator i=info_.find(ti);
if( info_.end()!=i ) if( info_.end()!=i )
{ {
shared_ptr<error_info_base const> const & p = i->second; shared_ptr<error_info_base const> const & p = i->second;
#ifndef BOOST_NO_RTTI #ifndef BOOST_NO_RTTI
BOOST_ASSERT( typeid(*p)==ti ); BOOST_ASSERT( BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti );
#endif #endif
return p; return p;
} }
@ -104,20 +105,11 @@ boost
} }
char const * char const *
diagnostic_information( char const * std_what, char const * exception_type_name ) const diagnostic_information() const
{ {
BOOST_ASSERT(exception_type_name!=0 && *exception_type_name ); if( diagnostic_info_str_.empty() )
if( what_.empty() )
{ {
std::string tmp; std::string tmp;
if( std_what )
{
tmp += std_what;
tmp += '\n';
}
tmp += "Dynamic exception type: ";
tmp += exception_type_name;
tmp += '\n';
for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i )
{ {
shared_ptr<error_info_base const> const & x = i->second; shared_ptr<error_info_base const> const & x = i->second;
@ -127,18 +119,18 @@ boost
tmp += x->value_as_string(); tmp += x->value_as_string();
tmp += '\n'; tmp += '\n';
} }
what_.swap(tmp); diagnostic_info_str_.swap(tmp);
} }
return what_.c_str(); return diagnostic_info_str_.c_str();
} }
private: private:
friend class exception; friend class exception;
typedef std::map< type_info_wrapper, shared_ptr<error_info_base const> > error_info_map; typedef std::map< type_info_, shared_ptr<error_info_base const> > error_info_map;
error_info_map info_; error_info_map info_;
mutable std::string what_; mutable std::string diagnostic_info_str_;
mutable int count_; mutable int count_;
void void

View File

@ -6,8 +6,8 @@
#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593 #ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593
#define UUID_FA5836A2CADA11DC8CD47C8555D89593 #define UUID_FA5836A2CADA11DC8CD47C8555D89593
#include <boost/exception/detail/get_boost_exception.hpp>
#include <boost/exception/enable_current_exception.hpp> #include <boost/exception/enable_current_exception.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <stdexcept> #include <stdexcept>
#include <new> #include <new>
@ -257,6 +257,34 @@ boost
} }
}; };
#ifdef BOOST_NO_RTTI
template <class T>
exception const *
get_boost_exception( T const * )
{
try
{
throw;
}
catch(
exception & x )
{
return &x;
}
catch(...)
{
return 0;
}
}
#else
template <class T>
exception const *
get_boost_exception( T const * x )
{
return dynamic_cast<exception const *>(x);
}
#endif
template <class T> template <class T>
inline inline
exception_ptr exception_ptr
@ -340,6 +368,7 @@ boost
{ {
return exception_detail::current_exception_std_exception(e); return exception_detail::current_exception_std_exception(e);
} }
#ifndef BOOST_NO_TYPEID
catch( catch(
std::bad_cast & e ) std::bad_cast & e )
{ {
@ -350,6 +379,7 @@ boost
{ {
return exception_detail::current_exception_std_exception(e); return exception_detail::current_exception_std_exception(e);
} }
#endif
catch( catch(
std::bad_exception & e ) std::bad_exception & e )
{ {

View File

@ -351,8 +351,10 @@ main()
test_std_exception_what<std::out_of_range>(); test_std_exception_what<std::out_of_range>();
test_std_exception_what<std::logic_error>(); test_std_exception_what<std::logic_error>();
test_std_exception<std::bad_alloc>(); test_std_exception<std::bad_alloc>();
#ifndef BOOST_NO_TYPEID
test_std_exception<std::bad_cast>(); test_std_exception<std::bad_cast>();
test_std_exception<std::bad_typeid>(); test_std_exception<std::bad_typeid>();
#endif
test_std_exception<std::bad_exception>(); test_std_exception<std::bad_exception>();
try try

View File

@ -38,12 +38,6 @@ error3:
{ {
}; };
std::string
get_diagnostic_information( std::exception const & x )
{
return boost::diagnostic_information(x);
}
int int
main() main()
{ {
@ -57,7 +51,7 @@ main()
catch( catch(
std::exception & x ) std::exception & x )
{ {
std::string di=get_diagnostic_information(x); std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos); BOOST_TEST(di.find("type:")!=std::string::npos);
BOOST_TEST(di.find("error1")!=std::string::npos); BOOST_TEST(di.find("error1")!=std::string::npos);
} }
@ -75,11 +69,26 @@ main()
catch( catch(
std::exception & x ) std::exception & x )
{ {
std::string di=get_diagnostic_information(x); std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos); BOOST_TEST(di.find("type:")!=std::string::npos);
#ifndef BOOST_NO_RTTI
BOOST_TEST(di.find("error2")!=std::string::npos); BOOST_TEST(di.find("error2")!=std::string::npos);
#endif }
catch(
... )
{
BOOST_TEST(false);
}
try
{
error2 x; x << tag_int(42);
BOOST_TEST(x.what()==std::string("error2"));
throw x;
}
catch(
boost::exception & x )
{
std::string di=boost::diagnostic_information(x);
BOOST_TEST(di.find("type:")!=std::string::npos);
BOOST_TEST(di.find("test_tag")!=std::string::npos); BOOST_TEST(di.find("test_tag")!=std::string::npos);
} }
catch( catch(
@ -96,9 +105,9 @@ main()
catch( catch(
boost::exception & x ) boost::exception & x )
{ {
std::string w1 = x.diagnostic_information(); std::string w1 = diagnostic_information(x);
x << tag_int(2); x << tag_int(2);
std::string w2 = x.diagnostic_information(); std::string w2 = diagnostic_information(x);
BOOST_TEST( w1!=w2 ); BOOST_TEST( w1!=w2 );
BOOST_TEST(w1.find("test_tag")!=std::string::npos); BOOST_TEST(w1.find("test_tag")!=std::string::npos);
BOOST_TEST(w2.find("test_tag")!=std::string::npos); BOOST_TEST(w2.find("test_tag")!=std::string::npos);

View File

@ -45,7 +45,26 @@ main()
catch( catch(
std::exception & x ) std::exception & x )
{ {
BOOST_TEST( 42==*boost::get_error_info<test_int>(x) ); #ifdef BOOST_NO_RTTI
try
{
throw;
}
catch(
boost::exception & x )
{
#endif
BOOST_TEST( boost::get_error_info<test_int>(x) );
if( boost::shared_ptr<int const> p=boost::get_error_info<test_int>(x) )
BOOST_TEST( 42==*p );
#ifdef BOOST_NO_RTTI
}
catch(
... )
{
BOOST_TEST(false);
}
#endif
BOOST_TEST( std::string(x.what())==std::string("exception test length error") ); BOOST_TEST( std::string(x.what())==std::string("exception test length error") );
} }
catch( catch(

View File

@ -10,12 +10,37 @@
struct throws_on_copy; struct throws_on_copy;
struct non_printable { }; struct non_printable { };
struct
user_data
{
int & count;
explicit
user_data( int & count ):
count(count)
{
++count;
}
user_data( user_data const & x ):
count(x.count)
{
++count;
}
~user_data()
{
--count;
}
};
typedef boost::error_info<struct tag_test_1,int> test_1; typedef boost::error_info<struct tag_test_1,int> test_1;
typedef boost::error_info<struct tag_test_2,unsigned int> test_2; typedef boost::error_info<struct tag_test_2,unsigned int> test_2;
typedef boost::error_info<struct tag_test_3,float> test_3; typedef boost::error_info<struct tag_test_3,float> test_3;
typedef boost::error_info<struct tag_test_4,throws_on_copy> test_4; typedef boost::error_info<struct tag_test_4,throws_on_copy> test_4;
typedef boost::error_info<struct tag_test_5,std::string> test_5; typedef boost::error_info<struct tag_test_5,std::string> test_5;
typedef boost::error_info<struct tag_test_6,non_printable> test_6; typedef boost::error_info<struct tag_test_6,non_printable> test_6;
typedef boost::error_info<struct tag_user_data,user_data> test_7;
struct struct
test_exception: test_exception:
@ -135,7 +160,9 @@ test_empty()
catch( catch(
test_exception & x ) test_exception & x )
{ {
BOOST_TEST( boost::exception_detail::get_boost_exception(&x) ); #ifndef BOOST_NO_RTTI
BOOST_TEST( dynamic_cast<boost::exception const *>(&x)!=0 );
#endif
} }
catch( catch(
... ) ... )
@ -256,6 +283,29 @@ test_add_tuple()
} }
} }
void
test_lifetime()
{
int count=0;
try
{
throw test_exception() << test_7(user_data(count));
BOOST_TEST(false);
}
catch(
boost::exception & x )
{
BOOST_TEST(count==1);
BOOST_TEST( boost::get_error_info<test_7>(x) );
}
catch(
... )
{
BOOST_TEST(false);
}
BOOST_TEST(!count);
}
int int
main() main()
{ {
@ -265,5 +315,6 @@ main()
test_basic_throw_catch(); test_basic_throw_catch();
test_catch_add_info(); test_catch_add_info();
test_add_tuple(); test_add_tuple();
test_lifetime();
return boost::report_errors(); return boost::report_errors();
} }

View File

@ -47,9 +47,26 @@ tester()
catch( catch(
T & y ) T & y )
{ {
BOOST_TEST(boost::get_error_info<test_data>(y)); #ifdef BOOST_NO_RTTI
if( boost::shared_ptr<int const> d=boost::get_error_info<test_data>(y) ) try
BOOST_TEST(*d==42); {
throw;
}
catch(
boost::exception & y )
{
#endif
BOOST_TEST(boost::get_error_info<test_data>(y));
if( boost::shared_ptr<int const> d=boost::get_error_info<test_data>(y) )
BOOST_TEST(*d==42);
#ifdef BOOST_NO_RTTI
}
catch(
... )
{
BOOST_TEST(false);
}
#endif
BOOST_TEST(y.x_==42); BOOST_TEST(y.x_==42);
} }
catch( catch(