diff --git a/doc/current_exception.html b/doc/current_exception.html
index d8b369b..b213da9 100644
--- a/doc/current_exception.html
+++ b/doc/current_exception.html
@@ -38,7 +38,7 @@ boost
Nothing.
Notes:
- It is unspecified whether the return values of two successive calls to current_exception refer to the same exception object.
-- Correct implementation of current_exception may require compiler support, unless enable_current_exception was used at the time the currently handled exception object was passed to throw. Whenever current_exception fails to properly copy the current exception object, it returns an exception_ptr to an object of type that is as close as possible to the original exception type, using unknown_exception as a final fallback. All such types derive from boost::exception, and:
- if the original exception object derives from boost::exception, then the boost::exception sub-object of the object referred to by the returned exception_ptr is initialized by the boost::exception copy constructor;
+- Correct implementation of current_exception may require compiler support (e.g. C++11 std::current_exception() is used when available, as specified by Boost.Config BOOST_NO_CXX11_HDR_EXCEPTION), unless enable_current_exception was used at the time the currently handled exception object was passed to throw. Whenever current_exception fails to properly copy the current exception object, it returns an exception_ptr to an object of type that is as close as possible to the original exception type, using unknown_exception as a final fallback. All such types derive from boost::exception, and:
diff --git a/include/boost/exception/detail/exception_ptr.hpp b/include/boost/exception/detail/exception_ptr.hpp
index d4eba62..c106ce2 100644
--- a/include/boost/exception/detail/exception_ptr.hpp
+++ b/include/boost/exception/detail/exception_ptr.hpp
@@ -412,11 +412,14 @@ boost
{
return exception_detail::current_exception_std_exception(e);
}
+#ifdef BOOST_NO_CXX11_HDR_EXCEPTION
+ // this case can be handled losslesly with std::current_exception() (see below)
catch(
std::exception & e )
{
return exception_detail::current_exception_unknown_std_exception(e);
}
+#endif
catch(
boost::exception & e )
{
@@ -425,7 +428,22 @@ boost
catch(
... )
{
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ try
+ {
+ // wrap the std::exception_ptr in a clone-enabled Boost.Exception object
+ exception_detail::clone_base const& base =
+ boost::enable_current_exception(std::current_exception());
+ return exception_ptr(shared_ptr(base.clone()));
+ }
+ catch(
+ ...)
+ {
+ return exception_detail::current_exception_unknown_exception();
+ }
+#else
return exception_detail::current_exception_unknown_exception();
+#endif
}
}
}
@@ -461,7 +479,20 @@ boost
rethrow_exception( exception_ptr const & p )
{
BOOST_ASSERT(p);
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ try
+ {
+ p.ptr_->rethrow();
+ }
+ catch(
+ const std::exception_ptr& std_ep)
+ {
+ // if an std::exception_ptr was wrapped above then rethrow it
+ std::rethrow_exception(std_ep);
+ }
+#else
p.ptr_->rethrow();
+#endif
BOOST_ASSERT(0);
#if defined(UNDER_CE)
// some CE platforms don't define ::abort()
diff --git a/test/unknown_exception_test.cpp b/test/unknown_exception_test.cpp
index bf474ba..8bed4c6 100644
--- a/test/unknown_exception_test.cpp
+++ b/test/unknown_exception_test.cpp
@@ -38,6 +38,25 @@ throw_unknown_exception()
throw test_exception();
}
+struct
+user_defined_exception
+ {
+ user_defined_exception(int d):data(d){}
+ int data;
+ };
+
+void
+throw_user_defined_exception()
+ {
+ throw user_defined_exception(42);
+ }
+
+void
+throw_builtin_exception()
+ {
+ throw 42;
+ }
+
int
main()
{
@@ -138,5 +157,115 @@ main()
BOOST_TEST(false);
}
}
+ try
+ {
+ throw_user_defined_exception();
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr ep=boost::current_exception();
+ try
+ {
+ rethrow_exception(ep);
+ }
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ catch(
+ user_defined_exception & x)
+ {
+ //Yay! std::current_exception to the rescue!
+ BOOST_TEST( 42==x.data );
+ }
+#else
+ catch(
+ boost::unknown_exception & )
+ {
+ //Boo! user defined exception was transported as a boost::unknown_exception
+ }
+#endif
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ try
+ {
+ rethrow_exception(ep);
+ }
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ catch(
+ user_defined_exception & x)
+ {
+ //Yay! std::current_exception to the rescue!
+ BOOST_TEST( 42==x.data );
+ }
+#else
+ catch(
+ boost::unknown_exception & )
+ {
+ //Boo! user defined exception was transported as a boost::unknown_exception
+ }
+#endif
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
+ try
+ {
+ throw_builtin_exception();
+ }
+ catch(
+ ... )
+ {
+ boost::exception_ptr ep=boost::current_exception();
+ try
+ {
+ rethrow_exception(ep);
+ }
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ catch(
+ int & x)
+ {
+ //Yay! std::current_exception to the rescue!
+ BOOST_TEST( 42==x );
+ }
+#else
+ catch(
+ boost::unknown_exception & )
+ {
+ //Boo! builtin exception was transported as a boost::unknown_exception
+ }
+#endif
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ try
+ {
+ rethrow_exception(ep);
+ }
+#ifndef BOOST_NO_CXX11_HDR_EXCEPTION
+ catch(
+ int & x)
+ {
+ //Yay! std::current_exception to the rescue!
+ BOOST_TEST( 42==x );
+ }
+#else
+ catch(
+ boost::unknown_exception & )
+ {
+ //Boo! builtin exception was transported as a boost::unknown_exception
+ }
+#endif
+ catch(
+ ... )
+ {
+ BOOST_TEST(false);
+ }
+ }
return boost::report_errors();
}