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 *
what() const throw()
{
return boost::exception::diagnostic_information();
return "example_io error";
}
protected:
@ -170,7 +170,7 @@ dump_all_info( boost::exception const & x )
dump_file_info(x);
dump_clib_info(x);
std::cout << "\nOutput from diagnostic_information():\n";
std::cout << x.diagnostic_information();
std::cout << diagnostic_information(x);
}
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
boost
{
template <class ErrorInfoTag>
template <class T>
inline
char const *
error_info_value()
type_name()
{
return BOOST_CURRENT_FUNCTION;
}
@ -23,40 +23,99 @@ boost
namespace
exception_detail
{
typedef detail::sp_typeinfo type_info_;
#ifdef BOOST_NO_TYPEID
typedef type_info_ type_info_wrapper;
#else
struct
type_info_wrapper
type_info_
{
type_info_ const * type;
detail::sp_typeinfo type_;
char const * name_;
explicit
type_info_wrapper( type_info_ const & t ):
type(&t)
type_info_( detail::sp_typeinfo type, char const * name ):
type_(type),
name_(name)
{
}
friend
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
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

View File

@ -6,27 +6,87 @@
#ifndef 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 <string>
namespace
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
std::string
diagnostic_information( std::exception const & x )
diagnostic_information( T const & x )
{
if( exception const * be = exception_detail::get_boost_exception(&x) )
return be->diagnostic_information();
else
return std::string("[ what: ") + x.what() + ", type: "
std::string di=
#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
+ typeid(x).name() +
std::string("Dynamic exception type: ")+BOOST_EXCEPTION_DYNAMIC_TYPEID(x)
#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()
{
}
char const *
diagnostic_information() const throw()
{
return boost::exception::_diagnostic_information(T::what());
}
};
struct large_size { char c[256]; };

View File

@ -6,11 +6,8 @@
#ifndef 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/intrusive_ptr.hpp>
#include <typeinfo>
namespace
boost
@ -24,12 +21,13 @@ boost
exception_detail
{
class error_info_base;
struct type_info_;
struct
error_info_container:
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 void set( shared_ptr<error_info_base const> const &, type_info_ const & ) = 0;
};
@ -37,7 +35,7 @@ boost
template <class ErrorInfo>
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
@ -49,7 +47,7 @@ boost
char const *
diagnostic_information() const throw()
{
return _diagnostic_information(0);
return _diagnostic_information();
}
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) )
//Force class exception to be abstract.
//Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected.
@ -92,6 +74,22 @@ boost
}
#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:
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>
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_;
};

View File

@ -6,9 +6,10 @@
#ifndef UUID_1A590226753311DD9E4CCF6156D89593
#define UUID_1A590226753311DD9E4CCF6156D89593
#include <boost/shared_ptr.hpp>
#include <boost/exception/detail/get_boost_exception.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/shared_ptr.hpp>
namespace
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>
inline
shared_ptr<typename ErrorInfo::value_type const>
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);
else
return shared_ptr<typename ErrorInfo::value_type const>();
}
#endif
}
#endif

View File

@ -7,9 +7,10 @@
#define UUID_8D22C4CA9CC811DCAA9133D256D89593
#include <boost/exception/exception.hpp>
#include <boost/exception/detail/error_info_base.hpp>
#include <boost/exception/error_info.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 <map>
@ -50,7 +51,7 @@ boost
char const *
tag_typeid_name() const
{
return exception_detail::type_name<Tag>();
return type_name<Tag>();
}
std::string
@ -84,19 +85,19 @@ boost
set( shared_ptr<error_info_base const> const & x, type_info_ const & typeid_ )
{
BOOST_ASSERT(x);
info_[type_info_wrapper(typeid_)] = x;
what_.clear();
info_[typeid_] = x;
diagnostic_info_str_.clear();
}
shared_ptr<error_info_base 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 )
{
shared_ptr<error_info_base const> const & p = i->second;
#ifndef BOOST_NO_RTTI
BOOST_ASSERT( typeid(*p)==ti );
BOOST_ASSERT( BOOST_EXCEPTION_DYNAMIC_TYPEID(*p)==ti );
#endif
return p;
}
@ -104,20 +105,11 @@ boost
}
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( what_.empty() )
if( diagnostic_info_str_.empty() )
{
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 )
{
shared_ptr<error_info_base const> const & x = i->second;
@ -127,18 +119,18 @@ boost
tmp += x->value_as_string();
tmp += '\n';
}
what_.swap(tmp);
diagnostic_info_str_.swap(tmp);
}
return what_.c_str();
return diagnostic_info_str_.c_str();
}
private:
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_;
mutable std::string what_;
mutable std::string diagnostic_info_str_;
mutable int count_;
void

View File

@ -6,8 +6,8 @@
#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593
#define UUID_FA5836A2CADA11DC8CD47C8555D89593
#include <boost/exception/detail/get_boost_exception.hpp>
#include <boost/exception/enable_current_exception.hpp>
#include <boost/exception/detail/type_info.hpp>
#include <boost/detail/atomic_count.hpp>
#include <stdexcept>
#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>
inline
exception_ptr
@ -340,6 +368,7 @@ boost
{
return exception_detail::current_exception_std_exception(e);
}
#ifndef BOOST_NO_TYPEID
catch(
std::bad_cast & e )
{
@ -350,6 +379,7 @@ boost
{
return exception_detail::current_exception_std_exception(e);
}
#endif
catch(
std::bad_exception & e )
{

View File

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

View File

@ -38,12 +38,6 @@ error3:
{
};
std::string
get_diagnostic_information( std::exception const & x )
{
return boost::diagnostic_information(x);
}
int
main()
{
@ -57,7 +51,7 @@ main()
catch(
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("error1")!=std::string::npos);
}
@ -75,11 +69,26 @@ main()
catch(
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);
#ifndef BOOST_NO_RTTI
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);
}
catch(
@ -96,9 +105,9 @@ main()
catch(
boost::exception & x )
{
std::string w1 = x.diagnostic_information();
std::string w1 = diagnostic_information(x);
x << tag_int(2);
std::string w2 = x.diagnostic_information();
std::string w2 = diagnostic_information(x);
BOOST_TEST( w1!=w2 );
BOOST_TEST(w1.find("test_tag")!=std::string::npos);
BOOST_TEST(w2.find("test_tag")!=std::string::npos);

View File

@ -45,7 +45,26 @@ main()
catch(
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") );
}
catch(

View File

@ -10,12 +10,37 @@
struct throws_on_copy;
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_2,unsigned int> test_2;
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_5,std::string> test_5;
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
test_exception:
@ -135,7 +160,9 @@ test_empty()
catch(
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(
... )
@ -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
main()
{
@ -265,5 +315,6 @@ main()
test_basic_throw_catch();
test_catch_add_info();
test_add_tuple();
test_lifetime();
return boost::report_errors();
}

View File

@ -47,9 +47,26 @@ tester()
catch(
T & y )
{
#ifdef BOOST_NO_RTTI
try
{
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);
}
catch(