How does std :: current_exception work?
Consider the following example:
class myclass
{
public:
void f() const
{
std :: cout << "Hello from myclass!" << std :: endl;
}
};
int main()
{
std :: exception_ptr x;
try
{
throw myclass();
}
catch(...)
{
x = std :: current_exception();
}
try
{
std :: rethrow_exception(x);
}
catch(const myclass & n)
{
n.f();
}
}
Here I am throwing a class object myclass
and using std :: current_exception()
in a block catch(...)
to get std :: exception_ptr
. Later I use std :: rethrow_exception
to get the exception again and I catch it, this time with catch(const myclass &)
, allowing me to call f()
and print , for example Hello from myclass!
.
Now. I imagine how I could implement something similar to std :: exception_ptr
: a pointer to the base class from which the template wrapper is inherited for every possible type, and some virtual method rethrow
that allows the exception to be thrown again. So far so good.
Now how does it work std :: current_exception()
? How is this implemented? I tried to test it using the Xcode me, but I have good flashing question mark: ?
. Is this some kind of primitive in C ++ 11? Like, for example, decltype
or sizeof
? Or is there another way to access the exception hidden in this catch(...)
?
For example, is there a way to just print the exception, whatever it is? Something like:
template <typename type> void printme(const type & exception)
{
try
{
throw exception;
}
catch(...)
{
std :: cout << /* SOME MAGIC HERE */ << std :: endl;
}
}
I am guessing I std :: current_exception()
will use some similar way to access the exception, make a copy of it, and create an instance std :: exception_ptr
that can be restored later.
Am I missing something? I've tried something trivial like catch(auto x)
, but it doesn't seem to do the job.
source to share
Before std::exception_ptr
was boost::exception_ptr
, who tries to implement this functionality without direct language support, and therefore requires more working code to work, With Boost, you need to wrap the exception at a point throw
with boost::enable_current_exception
and instead take out the wrapper. I haven't actually looked into the implementation, but my guess is that the shell copy constructor sets a local thread pointer pointing to itself ( throw
must copy its argument) which boost::current_exception
then retrieves (perhaps copying the exception to free storage first so it can survive the block catch
). To continue working, the catch (T x)
shell must wrap the original exception, inheriting from it, which makes it impossible to use with primitive types.
Another way is to copy the original, set the local stream pointer to point to the copy, and discard the original. This method works for any throwable type, but current_exception
will refer to a different instance than the one used to o initialize the parameter catch
.
Now std::exception_ptr
has direct language support and doesn't need to go through hoops or do over-copying to archive this, but the basic idea is the same: store the exception in a type-erasure container that can restore it at the point of being thrown and point to it.
source to share