Basically I want to simulate .NET Exception.InnerException in C++. I want to catch exception from bottom layer and wrap it with another exception and throw again to upper layer. The problem here is I don't know how to wrap the catched exception inside another exception.
struct base_exception : public std::exception
{
std::exception& InnerException;
base_exception() : InnerException(???) { } // <---- what to initialize with
base_exception(std::exception& innerException) : InnerException(innerException) { }
};
struct func1_exception : public base_exception
{
const char* what() const throw()
{
return "func1 exception";
}
};
struct func2_exception : public base_exception
{
const char* what() const throw()
{
return "func2 exception";
}
};
void func2()
{
throw func2_exception();
}
void func1()
{
try
{
func2();
}
catch(std::exception& e)
{
throw func2_exception(e); // <--- is this correct? will the temporary object will be alive?
}
}
int main(void)
{
try
{
func1();
}
catch(base_exception& e)
{
std::cout << "Got exception" << std::endl;
std::cout << e.what();
std::cout << "InnerException" << std::endl;
std::cout << e.InnerException.what(); // <---- how to make sure it has inner exception ?
}
}
In the above code listing I am not sure how to initialize the "InnerException" member when there is no inner exception. Also I am not sure whether the temporary object that is thrown from func1 will survive even after func2 throw?
Since C++ 11 you have new options:
You can use std::exception_ptr.
The exception is then preserve until last exception_ptr to this
exception is destroyed.
struct base_exception : public std::exception
{
std::exception_ptr InnerException;
base_exception() {}
base_exception(std::exception& innerException)
: InnerException(std::make_exception_ptr(innerException))
{}
};
Or you can simply use std::nested_exception.
You should also take a look at boost exception for an alternative solution to wrapping.
Also I am not sure whether the
temporary object that is thrown from
func1 will survive even after func2
throw?
No. Unless you rethrow the exception with throw;. You could implement this if you'd allow only some (limited) set of exception types.
//inversion of the problem :)
struct base_exception : public std::exception
{
std::list<base_exception*> snowball;
base_exception() { }
void add(base_exception* e) { snowball.push_back(e); }
};
void func2()
{
func2_exception e;
e.add(new func2_exception());
throw e;
}
void func1()
{
try
{
func2();
}
catch(base_exception& e)
{
e.add(new func1_exception());
throw e;
}
}
int main(void)
{
try
{
func1();
}
catch(base_exception& e)
{
std::cout << "Got exception" << std::endl;
//print info in the direct order of exceptions occurence
foreach(base_exception* exception, e.snowball)
{
std::cout << exception->what();
std::cout << "next exception was:" << std::endl;
}
}
}
hmmmm...
One problem with the inner exception is the possibility to throw it again while maintaining polymorphic behaviour.
This can be (somewhat) alleviate by actually managing the exception lifetime yourself and providing polymorphic copies.
// Base class
class exception: virtual public std::exception, private boost::noncopyable
{
public:
virtual exception* clone() const = 0;
virtual void rethrow() const = 0; // throw most Derived copy
};
// ExceptionPointer
class ExceptionPointer: virtual public std::exception
{
public:
typedef std::unique_ptr<exception> pointer;
ExceptionPointer(): mPointer() {}
ExceptionPointer(exception* p): mPointer(p) {}
ExceptionPointer(pointer p): mPointer(p) {}
exception* get() const { return mPointer.get(); }
void throwInner() const { if (mPointer.get()) mPointer->rethrow(); }
virtual char* what() const { return mPointer.get() ? mPointer->what() : 0; }
private:
pointer mPointer;
};
How to use ?
try
{
// some code
}
catch(exception& e)
{
throw ExceptionPointer(e.clone());
}
// later on
try
{
}
catch(ExceptionPointer& e)
{
e.throwInner();
}
As stated by others, boost::exception is a nice option. However, like all options that use a common base class approach, they rely on all thrown exceptions being derived from that base class. If your intermediary catch handlers need to add information to an exception from a third party library it won't work.
An option that might be sufficient is to have intermediary catch handlers like this:
catch (std::exception& ex)
{
std::string msg = ex.what();
msg.append(" - my extra info");
ex = std::exception(msg.c_str()); // slicing assignment
throw; // re-throws 'ex', preserving it's original type
}
This only works for implementations of std::exception that provide a constructor taking a string parameter (e.g. VC++). The std::exception constructor taking a string is a non-standard extension.
Related
During the member initialisation of a class with multiple members, it seems desirable to be able to catch an exception generated by any specific member initialiser, to wrap in additional context for rethrowing, but the syntax of a function-try-block doesn't appear to accomodate that.
#include <stdexcept>
#include <string>
#include <sstream>
using namespace std::literals::string_literals;
[[noreturn]]
int thrower() { throw std::runtime_error("unconditional throw"s); }
int nonThrower() { return 3; }
class C {
int x;
int y;
public:
C();
};
class XError : public std::runtime_error {
public:
XError(const std::string& what) : std::runtime_error((std::stringstream() << "xerror: "s << what).str()) {};
};
class YError : public std::runtime_error {
public:
YError(const std::string& what) : std::runtime_error((std::stringstream() << "yerror: "s << what).str()) {};
};
C::C() try:
x(nonThrower()),
y(thrower()) {}
catch(const std::exception& e) { /* ... */ }
In the above trivial example, on the final line, I would very much like to be able to throw XError() if the exception occurs in initialisation of .x, and YError() if the exception occurs in initialisation of .y.
Ideally I'd like to be able to do something like
// -std=c++3000
C::C():
try: x(nonThrower()) catch(const std::exception& e) { throw XError(e.what()); },
try: y(thrower()) catch(const std::exception& e) { throw YError(e.what()); } {}
But it seems my only option is to write separate functions per initialiser member which wrap the exceptions themselves, then use those in the member initialisers. Given how ghastly member initialiser syntax is, this will probably read better, but it's less compact and more non-linear, which is less than ideal. For completeness:
int makeX() {
try { return nonThrower(); }
catch(const std::exception& e) { throw XError(e.what()); }
}
int makeY() {
try { return thrower(); }
catch(const std::exception& e) { throw YError(e.what()); }
}
C::C():
x(makeX()),
y(makeY()) {}
Please excuse any antipatterns or mistakes in my C++. I am both very new to the language and not as smart as you might hope me to be.
Is it possible to have a function-try-block per member initialiser?
No, that is not possible.
Sidebar: it seems like you're overusing and/or overthinking exceptions. Most people don't write much exception-handling code, because most programs are fine with just terminating if an exception is thrown, in most places. Of course there are exceptions to this rule, but if you're new to C++ and you're getting hung up on this, you should probably revisit your approach and not make your program so reliant on fine-grained exception handling.
It's not possible, but if you want to go down the exception route you can write function wrappers:
template<typename Exn, typename T>
T catch_with(T (*fn)()) // or, std::function<T()> fn
{
try { return fn(); }
catch(const std::exception& e) { throw Exn(e.what()); }
}
C::C():
x(catch_with<XError>(nonThrower)),
y(catch_with<YError>(thrower) {}
This is about wrapping the exception handling logic in some sort of class. While writing c++
code, many time we need to catch many type/variants of exception depending on what client throw. This lead us to write similar types of code(many times) in catch() clause.
In below sample example, I have written the function(), which can throw exception in the many possible form.
I wanted to know is it possible to write/wrap such logic in the form of class so that end user would have to write similar types of code at once place?. Does it make any sense or it has any meaning?
#include<vector>
#include<string>
#include<exception>
#include<iostream>
// this function can throw std::exception, std::string, int or unhandled
void function() {
std::vector<int> x{1,2,3,4,5};
auto val = x.at(x.size()); //throw out-of-range error
}
int main() {
try { function(); }
catch(std::exception& e) { std::cout<<e.what()<<std::endl; }
catch(std::string& msg) { std::cout<<msg<<std::endl; }
catch(int i) { std::cout<<i<<std::endl; }
catch(...) { std::cout<<"Unhandled Exception"<<std::endl; }
return 0;
}
So far I thought in this way and below is the pseudo logic.
class exceptionwrapper{
exceptionwrapper(function pointer* fp) {
// functions which would be executing inside try
}
~exceptionwrapper() {
// all catch() clause can be written over here
// or some other member function of this class
}
};
The object of this class can be instantiated in the main() in this way.
int main() {
exceptionwrapper obj(function);
//here execptionwrapper destructor would take care about calling all type of catch
}
It is possible using std::exception_ptr:
Live demo link.
#include <iostream>
#include <exception>
#include <stdexcept>
void universal_exception_handler(std::exception_ptr e)
{
try
{
std::rethrow_exception(e);
}
catch (const std::logic_error& e)
{
std::cout << "logic_error" << std::endl;
}
catch (const std::runtime_error& e)
{
std::cout << "runtime_error" << std::endl;
}
}
void foo()
{
throw std::logic_error{""};
}
void bar()
{
throw std::runtime_error{""};
}
int main()
{
try
{
foo();
}
catch (...)
{
universal_exception_handler(std::current_exception());
}
try
{
bar();
}
catch (...)
{
universal_exception_handler(std::current_exception());
}
}
You can also achieve this without std::exception_ptr, just put throw; in place of std::rethrow_exception(e);, hoping this function will be invoked only if there is an active exception being handled (otherwise your program will be terminate()'ed):
void universal_exception_handler()
{
try
{
throw;
}
catch (const std::logic_error& e)
{
std::cout << "logic_error" << std::endl;
}
catch (const std::runtime_error& e)
{
std::cout << "runtime_error" << std::endl;
}
}
try
{
foo();
}
catch (...)
{
universal_exception_handler();
}
Yet another live demo link.
What you're asking for is possible, but I don't think it's very useful. First let's implement a mechanism to accept a callable object, and its associated arguments, which we'll invoke in the destructor of exception_wrapper.
template<typename Func, typename... Args>
struct exception_wrapper
{
exception_wrapper(Func f, Args... args)
: f_(std::move(f))
, args_(std::make_tuple(std::move(args)...))
{}
~exception_wrapper()
{
try {
invoke();
} catch(std::exception const& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Caught unknown exception" << std::endl;
}
}
template<std::size_t... I>
void apply(std::index_sequence<I...>)
{
f_(std::get<I>(args_)...);
}
void invoke()
{
apply(std::index_sequence_for<Args...>());
}
Func f_;
std::tuple<Args...> args_;
};
template<typename Func, typename... Args>
auto make_exception_wrapper(Func&& f, Args&&... args)
{
return exception_wrapper<Func, Args...>(
std::forward<Func>(f), std::forward<Args>(args)...);
}
This makes use of the C++14 std::integer_sequence; if that's not available on your implementation there are several answers on SO that show how to implement it yourself (this one for instance).
To use it, create an exception_wrapper object, and your function will be invoked when the destructor executes.
make_exception_wrapper(function);
Live demo
Now, I don't think this is useful because in general you should only catch exceptions if your code is able to handle them, and continue operating normally. Otherwise let them propagate to the top level where you might want to install a handler so it allows you to exit the program gracefully.
Given that, it's unlikely that there'll be a common approach to handling all exceptions thrown by your code, which greatly reduces the utility of exception_wrapper as implemented. You could modify it to take another callable argument, the exception handler that will be passed the std::exception object that was caught, which makes the class a little more generic.
Additionally, invoking the function in the destructor means you cannot pass the return value, if any, back to the caller. This can be fixed by invoking the function within exception_wrapper::operator() instead, but that then adds the wrinkle of what to return in the case an exception is indeed thrown, and you've suppressed it.
Finally, do not write code that throws types that are not derived from std::exception. This makes your code unidiomatic, and if you do want to handle the exception, you'll need to litter the code with several catch statements, like you have in your example.
I like boost::exception quite a bit, but I'm quite bothered it does not provide a proper what() function out of the box. Now don't get confused, it does have a nice boost::diagnostic_information that contains all the information I would like to see in my hypothetic what() function but since boost::exception does not inherit from std::exception the what() function I get if I multiple inherit (as suggested from the tutorial, see line below) is the default useless what() from the std::exception base that explains nothing about the exception.
struct my_exception: virtual std::exception, virtual boost::exception { };
Now obviously I tried to override what() and make it return boost::diagnostic_information but somehow it just does not work, so I'm a bit puzzled. That might be because it would loop but I'm not quite sure.
PS: The reason I want to implement what() right is that it is shown by default by a lot of tools if your program dies from them (e.g. the gnu compiler will show a nice fatal error, and display what(), boost unit tests tools etc.).
Here's a link to the test code below
#include <boost/exception/all.hpp>
struct my_exception: virtual std::exception, virtual boost::exception {};
struct my_exception2: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return "WHAT";
}
};
struct my_exception3: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return boost::diagnostic_information(this).c_str();
}
};
int main() {
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//This is useless ___ std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const boost::exception& e){
std::cout << boost::diagnostic_information(e) << std::endl;
//This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception2());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//Overriding what usually works ___ WHAT
}
try {
BOOST_THROW_EXCEPTION(my_exception3());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//But somehow here it does not work ___ Unknown exception.
}
}
First, boost::diagnostic_information takes an exception by (const) reference, and this is a pointer:
return boost::diagnostic_information(*this).c_str();
^-- here
Second, once you've fixed that, as you've correctly anticipated this results in infinite recursion as boost::diagnostic_information calls std::exception::what(). It is possible to work around this with a guard member or something similar:
struct my_exception3: std::exception, boost::exception {
mutable bool in_what = false;
virtual const char* what() const throw() {
struct g { bool &b; ~g() { b = false; } } guard{in_what};
return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
}
};
Finally, you're using c_str from a destructed temporary string. I'll leave the solution to that problem as an exercise.
And the winner is...
namespace boost {
char const * diagnostic_information_what( boost::exception const & e ) throw();
}
What is the type of the exception object in the following thrown:
Question1> range_error r("error"); throw r;
Answer1> an object of range_error
Question2> exception *p = &r; throw *p;
Answer2> a sliced object of exception
Question3> exception *p = &r; throw p;
Answer3> a pointer pointing to range_error is thrown. The capture-handling can access the range_error member functions through dynamic binding.
Do I get these question right?
// Updated and Compiled and Run on VS2010
#include <iostream>
using namespace std;
class ExClassA
{
public:
virtual void PrintMe() const
{
cout << "ExClassA" << endl;
}
};
class ExClassB : public ExClassA
{
public:
virtual void PrintMe() const
{
cout << "ExClassB" << endl;
}
};
int main(int argc, char* argv[])
{
ExClassB exClassB;
ExClassA *p = &exClassB;
try
{
throw *p;
}
catch (const ExClassA& e)
{
e.PrintMe();
}
try
{
throw p;
}
catch (const ExClassA* e)
{
e->PrintMe();
}
}
The first try-catch of above program prints "ExClassA"
The second try-catch of above program prints "ExClassB"
Throwing an object always results in the thrown object being a copy of the object you threw, based on the static type of that object. Thus your first two answers are correct.
The third one is a little more complicated. If you catch(range_error*) you won't catch the exception because the types don't match. If you catch(exception*) you won't be able to access members of range_error in the caught pointer; you can dynamic_cast that pointer back to a range_error pointer though.
I think you are right in all three. The type of the thrown object (IIRC) is the static type of the object being thrown. I would have to dig into the standard for a while to find the exact quotes, but a simple example seems to confirm this:
struct base {};
struct derived : base {};
void t() {
derived d;
base * b = &d;
throw *b;
}
int main() {
try {
t();
} catch ( derived const & ) {
std::cout << "derived" << std::endl;
} catch ( base const & ) {
std::cout << "base" << std::endl;
}
}
If the dynamic type of the object being thrown was used, then *b would have type derived and the first catch would succeed, but empirically the second catch is executed (g++).
In the last case, the object thrown is a pointer to exception that refers to a range_error object. The slight difference is again what can be caught, the compiler will not catch in a catch (range_error*) block. The answer is correct, but I would have specified the type of the pointer, as much as the type of the pointee. (The type of the pointer is somehow implicit in the answer)
All three answers are correct. Just note that you'll have to catch a
pointer type in the third case.
The usual way to throw an exception is:
throw range_error("error");
At the throw site, you normally know the exact type of exception you
want to throw. About the only exception I can think of is when the
exception was passed in as an argument, e.g.:
void f( std::exception const& whatToDoInCaseOfError )
{
// ...
throw whatToDoInCaseOfError; // slices
}
It's not a frequence case, but if you want to support it, you'll need a
separate exception hierarchy of your own, with a virtual raise
function:
class MyExceptions
{
public:
virtual ~MyExceptions() {}
virtual void raise() const = 0;
};
template<typename ExceptionType>
class ConcreteException : public ExceptionType, public MyExceptions
{
public:
virtual void raise() const
{
throw *this;
}
};
The client code then wraps the exception he wants to be thrown in a
ConcreteException, and you call the raise function on it, rather
than invoke throw directly.
I want to call a function that may throw an exception. If it does throw an exception, I want to catch it and pass the exception object to a handler function. The default implementation of the handler function is simply to throw the exception. Here is whittled-down code to illustrate the issue:
struct base_exception : exception {
char const* what() const throw() { return "base_exception"; }
};
struct derived_exception : base_exception {
char const* what() const throw() { return "derived_exception"; }
};
void exception_handler( base_exception const &e ) {
throw e; // always throws a base_exception object even if e is a derived_exception
}
int main() {
try {
throw derived_exception();
}
catch ( base_exception const &e ) {
try {
cout << e.what() << endl; // prints "derived_exception" as expected
exception_handler( e );
}
catch ( base_exception const &e ) {
cout << e.what() << endl; // prints "base_exception" due to object slicing
}
}
}
However, the throw e in exception_handler() throws a copy of the static type of the exception, i.e., base_exception. How can I make exception_handler() throw the actual exception having the correct run-time type of derived_exception? Or how can I redesign things to get what I want?
You can put a throw_me virtual function in the base exception class, and have every derived class override it. The derived classes can throw the proper most derived type, without slicing. Even though the function has the same definition in each class, they're not the same - the type of *this is different in each case.
struct base_exception : exception
{
char const* what() const throw() { return "base_exception"; }
virtual void throw_me() const { throw *this; }
};
struct derived_exception : base_exception
{
char const* what() const throw() { return "derived_exception"; }
virtual void throw_me() const { throw *this; }
};
void exception_handler( base_exception const &e ) {
e.throw_me();
}
You can use throw; to re-throw the exception that was caught. You could also use a template.
template<typename T> void rethrow(const T& t) { throw t; }
Throw by value, catch by reference. It'll save you a lot of headaches.
What you are looking for is called "propagating" the exception. To do so, you have to use the throw keyword without parameters inside the catch block. It will not copy the exception and the exception will be caught by the next catch block on its way or will make your program abort if it's not caught again.