How can I abstract out a repeating try catch pattern in C++ - c++

I have a pattern that repeats for several member functions that looks like this:
int myClass::abstract_one(int sig1)
{
try {
return _original->abstract_one(sig1);
} catch (std::exception& err) {
handleException(err);
} catch (...) {
handleException();
}
}
bool myClass::abstract_two(int sig2)
{
try {
return _original->abstract_two(sig2);
} catch (std::exception& err) {
handleException(err);
} catch (...) {
handleException();
}
}
[...]
int myClass::abstract_n(bool sig3a, short sig3b)
{
try {
return _original->abstract_n(sig3a, sig3b);
} catch (std::exception& err) {
handleException(err);
} catch (...) {
handleException();
}
}
Where abstract one through n are methods of a pure virtual abstract interface for which myClass and _original are concrete implementations.
I don't like that this pattern repeats in the code and would like to find a way to eliminate the repeating try / catch pattern and code as a single abstraction, but I can't think of a good way to do this in C++ without macros. I would think that there is a way with templates to do this better.
Please suggest a clean way to refactor this code to abstract out the repeated pattern.

I asked a very similar conceptual question, see Is re-throwing an exception legal in a nested 'try'?.
Basically, you can move the various exception handlers to a separate function by catching all exceptions, calling the handler and rethrowing the active exception.
void handle() {
try {
throw;
} catch (std::exception& err) {
handleException(err);
} catch (MyException& err) {
handleMyException(err);
} catch (...) {
handleException();
}
}
try {
return _original->abstract_two(sig2);
} catch (...) {
handle();
}
It scales well with more different exception kinds to differenciate. You can pack the first try .. catch(...) into macros if you like to:
BEGIN_CATCH_HANDLER
return _original->abstract_two(sig2);
END_CATCH_HANDLER

One option, if there are a limited number of function arities, would be to use a function template:
template <typename ReturnT, typename ClassT>
ReturnT call_and_handle(ClassT* obj, ReturnT(ClassT::*func)())
{
try {
return (obj->*func)();
}
catch (const std::exception& ex) {
handleException(ex);
}
catch (...) {
handleException();
}
return ReturnT();
}
This assumes that handleException is some non-member function, but it is easy to modify it if it is a member function. You need to decide what call_and_handle returns if an exception is handled; I have it returning an initialized ReturnT as a placeholder.
This reduces your member functions to:
int myClass::abstract_one()
{
return call_and_handle(_original, &myClass::abstract_one);
}
You would need a separate function template for calling functions that have one parameter, two parameters, etc.
If you have functions that have an unwieldy number of parameters and you were really desperate, you could use a macro (I wouldn't really recommend this, though):
#define CALL_AND_HANDLE(expr) \
try { \
return (expr); \
} \
catch (const std::exception& ex) { \
handleException(ex); \
} \
catch (...) { \
handleException(); \
}
Which can be used as:
int myClass::abstract_one()
{
CALL_AND_HANDLE(_original->myClass::abstract_one());
}
As an aside, if you catch (...) and do not rethrow the caught exception, you should in most cases terminate the program.

As a variant on Alexander Gessler's solution you can omit some of the braces that make this implementation a little long. It does exactly the same thing, just with a little less { } verbage.
void handle() try
{
throw;
}
catch (std::exception& err)
{
handleException(err);
}
catch (MyException& err)
{
handleMyException(err);
}
catch (...)
{
handleException();
}
int myClass::abstract_one(int sig1) try
{
return _original->abstract_one(sig1);
}
catch (...)
{
handle();
return -1;
}

My answer is conceptually similar to James McNellis', except that I use boost::bind to do the heavy lifting:
using boost::bind;
class myClass
{
public:
myClass(origClass * orig) : orig_(orig) {}
int f1(bool b) { return wrapper(bind(&origClass::f1, orig_, b)); }
bool f2(int i) { return wrapper(bind(&origClass::f2, orig_, i)); }
void f3(int i) { return wrapper(bind(&origClass::f3, orig_, i)); }
private:
origClass * orig_;
template <typename T>
typename T::result_type wrapper(T func)
{
try {
return func();
}
catch (std::exception const &e) {
handleError(e);
}
catch (...) {
handleError();
}
}
};
Note that I wouldn't use a boost::function here as it can interfere with inlining.

My answer is: do nothing at all. The first code example as shown is fine. So what is there's repetition? It is plain and clear, and does what it looks like it does. It can be understood with no extra mental burdens past the code seen and general knowledge of C++.
Consider your motive for asking this question.
Where I'm coming from is past projects where code had to be examined by others - not PhD Comp Sci experts, but federal inspectors, mechanical engineers, self-taught programmers, scientists, etc. Smart people, all of them (or most of them), but only an off-the-deep-end chrome dome PhD, or a younger programmer out to impress everyone with their hi IQ, would appreciate the clever "solutions" to this question. For the places I've been, nothing beats plain clear code that does what it says, with no mental burden of having to keep in mind the meaning of dozens of classes, macros, etc. and recognizing "design pattern" understood properly only be experienced software engineers.
Increasingly, I find C++ (and Java and C#) code becoming more sophisticated in a coding sense, but needing to be understood by non-experts in C++.
Of course YMMV, depending on the intended audience and source of potential future maintenence programmers. Sometimes clever coding is necessary to achieve certain goals. Is your case an example?

I don't have an answer except to suggest that you might be better off avoiding exception handling altogether and relying instead on Smart Pointers and Boost Scope Exit to do all your resource clean up. That way you won't have to catch exceptions unless you can do something about them, which is rarely the case. Then you can do all exception handling in one centralized place higher up the call chain for error reporting and such.

Use boost::function and boost::bind. Works with any function signature so long as the return type matches;
#include <boost/function.hpp>
#include <boost/bind.hpp>
using boost::function;
using boost::bind;
template<typename T>
T exception_wrapper(boost::function<T()> func)
{
try {
return func();
} catch (std::exception& err) {
handleException(err);
} catch (...) {
handleException();
}
}
// ways to call
int result = exception_wrapper<int>(bind(libraryFunc, firstParam));
// or a member function
LibraryClass* object;
result = exception_wrapper<int>(bind(&LibraryClass::Function, object, firstParam));
// So your wrapping class:
class YourWrapper : public SomeInterface
{
public:
int abstract_one(int sig1)
{
return exception_wrapper<int>(bind(&LibraryClass::concrete_one, m_pObject, sig1));
}
bool abstract_two(int sig1, int sig2)
{
return exception_wrapper<bool>(bind(&LibraryClass::concrete_two, m_pObject, sig1, sig2));
}
// ...
private:
LibraryClass* m_pObject;
};

A bit of an old question, but these days we can also craft an elegant generic solution with variadic templates and std::invoke. (Requires C++17)
template<typename Action, typename... Args>
int MyClass::abstract(Action action, Args&&... args)
{
try {
return std::invoke(action, std::forward<Args>(args)...);
} catch (std::exception& err) {
handleException(err);
} catch (...) {
handleException();
}
}
Here action can be a lambda, function pointer, or even member function pointers thanks to std::invoke. For example:
my_class->abstract(&Original::abstract_n, original, sig3a, sig3b);

Related

Translate exception from one type to another

If have some framework that expects callbacks of a type like
void fcn(F& data);
It can handle exceptions of type ExF.
In my callback, I am using some third party library that throws exceptions of type ExL. So my callbacks look like
void fcn1(F& data)
{
try
{
// call library
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
Now I want to write more callbacks fcn2, fcn3, ... that use the library but do not want to repeat the same try/catch all the time. In particular, maybe I will add another
catch(const ExL2& ex)
block in the future for several callbacks. I cannot change the code (in particular the exception types) in the framework and the library. How can I avoid repeating the try/catch blocks?
Take advantage of the fact that while you are in a catch block, you have a "currently handled exception" that you can just throw; again. This allows you to move the logic into another function
void except_translate() {
try
{
throw;
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
void fcn1(F& data)
{
try
{
// call library
}
catch(...)
{
except_translate();
}
}
This technique is known (for googling purposes) as a Lippincott function. It centralizes the error translation logic into one place, so you can easily extend that one function with another handler and it will translate it for all functions that use this utility.
Write a wrapper that does the translation for you.
template <typename Func, typename ... Args>
decltype(auto) translate(Func func, Args&&... args)
{
try {
return func(std::forward<Args>(args)...);
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
Now you can F data; translate(fcn, data) and it works the same way as fcn1(data).
EDIT above code doesn't work as a callback unless one wraps it further (in a lambda for example). Here's an alternative approach:
template <typename Res, typename ... Args>
auto
translate(Res (&func)(Args...)) ->
std::function<Res(Args...)>
{
try {
return [&](Args&& ... args) { return func(std::forward<Args>(args)...); };
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
Then your callback is translate(fcn).
Both of these are very general, if you only need to wrap one type of callback, here's an easy way:
template<void FCT(F& data)>
void translate(F& data)
{
try {
FCT(data);
}
catch(const ExL& ex) {
ExF exf = make_ExF(ex);
throw exf;
}
}
and the callback is translate<fcn>.
(This is basically the same as your answer but with a standalone function instead of a static member).
This is a solution based on the idea of n.m.:
void fcn1_inner(F& data)
{
// call library, no try/catch
}
template<void FCT(F& data)> struct Wrapper
{
static void FN(F& data)
{
try
{
FCT(data);
}
catch(const ExL& ex)
{
ExF exf = make_ExF(ex);
throw exf;
}
}
};
The callback is now
Wrapper<fcn1_inner>::FN

Initializing object which throws exceptions

I have class A, which has constructor A(string filepath)
class A {
public:
A(string filePath);
private:
A();
}
I need to initialize A, and use it later. Constructor A throws exceptions.
int main() {
A a;
try {
a = A("./my/file/path");
} catch (exception e) {
return 1;
}
// Use a
return 0;
}
What would be the most elegant solution? (I dont want to have something like init function, because it makes it possible to have empty A object.)
The most elegant solution is probably to move all your logic which uses a into a function
int use_a(A &a);
int main() {
try {
A a("./my/file/path");
// if we reach here, no exception was thrown
// hence a is safe to use
return use_a(a);
} catch (exception e) {
// if we reach here a never really existed
return 1;
}
}
You're correct to prefer avoiding two-phase initialization - this way use_a can implicitly rely on a being safe to use.
The most elegant solution is:
int main() {
try {
A a("...");
// use a
} catch (const std::exception& e) {
// log e
return 1;
}
return 0;
}
If you don't want empty A objects consider deleting the default constructor. Note that this makes using some stl containers more difficult, while ensuring no invalid object exists.
In addition to that i think using throw in constructors very much allowed. If you don't want to do that consider the noexcept keyword. Note that throws in destructors can cause problems and are usually avoided.
As alternative, you might turn the exception in "optional/checkable" construction with std::optional or std::unique_ptr:
std::optional<A> MakeA(const std::filesystem::path& path)
{
try {
return A{path};
} catch (std::exception& e) {
return std::nullopt;
}
}
int main() {
auto a = MakeA("./my/file/path");
if (!a) {
return 1;
}
// Use *a
return 0;
}

How to catch a constructor exception?

I have a C++ class which throws an exception from the constructor on failure. How can I allocate a local instance of this class (without using new) and handle any possible exceptions, while keeping the try block scope as small as possible?
Essentially, I am looking for the C++ equivalent of the following Java idiom:
boolean foo() {
Bar x;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x.doSomething();
return true;
}
I do not want to catch exceptions from x.doSomething(), only the constructor.
I suppose what I'm looking for is a way to separate the declaration and the initialization of x.
Is it possible to accomplish this without using heap allocations and pointers?
You can use std::optional from C++17:
bool foo() {
std::optional<Bar> x; // x contains nothing; no Bar constructed
try {
x.emplace(); // construct Bar (via default constructor)
} catch (const Exception& e) {
return false;
}
x->doSomething(); // call Bar::doSomething() via x (also (*x).doSomething() )
return true;
}
This Java idiom doesn't translate well to C++ since Bar x; will require default constructor even if your real constructor requires arguments to be passed.
I'd advise fighting the language to this degree - widening the try block is sufficient - but if you really want to narrow then you could use a function and rely on return value optimisation to obviate a value copy:
Bar foobar()
{
try {
return Bar();
} catch (Exception& e){
/* Do something here like throwing a specific construction exception
which you intercept at the call site.*/
}
}
But really, you could throw a specific exception on construction, so obviating this function approach entirely.
Yes it's possible, if you put all the code in the try clause, for example by using a function try block (to avoid unnecessary nesting and scoping):
bool foo() try
{
Bar x;
x.doSomething();
return true;
}
catch (std::exception const& e)
{
return false;
}
Or in the try clause call another function which does the real work:
void real_foo()
{
Bar x;
x.doSomething();
}
bool foo() try
{
real_foo();
return true;
}
catch (std::exception const& e)
{
return false;
}
Note that it's often not a good idea to throw exceptions in a constructor, as that will halt the construction of the object, and its destructor will not be called.
As noted by Holt, this will also catch exceptions from the doSomething call. There are two ways of solving that:
The simple and standard way: Use pointers.
Use two-stage construction: Have a default constructor which can't throw exceptions, then call a special "construct" function that can throw exceptions.
The second way was common before C++ was standardized, and used extensively in code for the Symbian system. It is not common any more since using pointers for this is much more easy and simpler, especially today with good smart pointers available. I really don't recommend the second way in modern C++.
The easiest way is of course to make sure that the constructor can't throw exceptions at all, or if any is thrown then they are of the nature that the program can't continue anyway and have the program be terminated. As noted in the comments to your question, exceptions in C++ are expensive, and then we also have the abandoned construction issue, and in all using exceptions in C++ should only be done in exceptional cases. C++ is not Java, you should not treat it as such even if there are similar constructs in both languages.
If you still want to throw exceptions from the constructor there is actually a third way to catch only those: Use one of the code-example up top, and throw only specific exceptions that doSomething can never throw and then catch these specific constructors only.
Normally if you want to avoid heap allocations, you can't separate the declaration of a local variable from its definition. So if you were to combine everything in a single function, you would have to do surround the entire scope of x with try/catch block:
boolean foo() {
try {
Bar x;
x.doSomething();
} catch (Exception e) {
return false;
}
return true;
}
No. From your java example, you will have to choose between these 2 possibilities:
Without pointers:
bool foo() {
try {
Bar x;
x.doSomething();
} catch (Exception e) {
return false;
}
return true;
}
With pointers:
bool foo() {
Bar* x = nullptr;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x->doSomething();
delete x; // don't forget to free memory
return true;
}
Or using managed pointers:
#include <memory>
bool foo() {
std::unique_ptr<Bar> x;
try {
x = new Bar(); // until C++14
x = std::make_unique<Bar>(); // since C++14
} catch (Exception e) {
return false;
}
x->doSomething();
return true;
}
You have to choose between variant of
bool foo() {
std::unique_ptr<Bar> x;
try {
x = std::make_unique<Bar>();
} catch (const BarConstructorException& e) {
return false;
}
x->doSomething();
return true;
}
or
bool foo() {
try {
Bar x;
x.doSomething();
} catch (const BarConstructorException& e) {
return false;
}
return true;
}
In the revised question the OP adds the requirement that
” I do not want to catch exceptions from x.doSomething(), only the constructor [of the local variable].
A simple way to translate the Java code
boolean foo() {
Bar x;
try {
x = new Bar();
} catch (Exception e) {
return false;
}
x.doSomething();
return true;
}
… to C++, is then to use an Optional_ class (like Barton-Nackmann Fallible, boost::optional or C++17 std::optional)
auto foo()
-> bool
{
Optional_<Bar> xo;
try
{
xo.emplace();
}
catch( ... )
{
return false;
}
Bar& x = *xo;
// Possibly other code here, then:
x.doSomething();
return true;
}
A nice alternative is to refactor that code, like this:
struct Something_failure {};
void do_something( Bar& o )
{
// Possibly other code here, then:
o.doSomething();
}
auto foo()
-> bool
{
try
{
Bar x;
do_something( x );
return true;
}
catch( Something_failure const& )
{
throw;
}
catch( ... )
{}
return false;
}
If you do not like the above approaches then you can always go for a dynamically allocated Bar instance, e.g. using a std::unique_ptr for guaranteed cleanup, which however has the general overhead of a dynamic allocation. In Java most every object is dynamically allocated so that might not seem to be a serious disadvantage. But in C++ most objects are superfast stack-allocated so that a dynamic allocation is a very slow operation compared to ordinary operations, so the possible conceptual simplicity of dynamic allocation must be weighted against that.

reduce if statements when checking result

My C++ function has many if statements checking the returning value of called functions:
Result func(...){
if (SUCCESS != func1(...))
return ERROR;
// do something
if ( SUCCESS != func2(...))
return ERROR;
// do something else
if (SUCCESS != func3(...))
return ERROR;
// do something
.
.
.
}
Is there anyway for eliminating or reducing the if statements here?
For example I want something like this:
Result func(...){
Result result = SUCCESS;
when (result != SUCCESS) return ERROR;
result = func1(...);
// do something
result = func2(...);
// do something else
result = func3(...);
// do something
.
.
.
}
I cannot help myself, but to write solution which might be considered over-engineering, but it allows to prepare single template class for all results (for future use) and then minimize code for actual usage (no need to use checking methods or macros, no need to write own wrappers except this single result holder template class). Enjoy :D.
#include <iostream>
template<class T>
class Result
{
public:
Result() :
m_value(),
m_badValue()
{
}
Result(const T& value, const T& badValue) :
m_value(value),
m_badValue(badValue)
{
}
void operator=(const T& value)
{
if(value == m_badValue)
{
throw "Bad Value!";
}
else
{
m_value = value;
}
}
operator const T&() const
{
return m_value;
}
const T& value() const
{
return m_value;
}
private:
T m_value;
T m_badValue;
};
static const int SUCCESS = 0;
static const int FAIL = -1;
int func1()
{
return SUCCESS;
}
int func2()
{
return SUCCESS;
}
int func3()
{
return FAIL;
}
int main()
{
Result<int> result(FAIL, FAIL);
try
{
result = func1();
result = func2();
result = func3();
}
catch (const char *error)
{
::std::cout << "Error: " << error << ::std::endl;
}
::std::cout << "Last value: " << static_cast<int>(result) << " - " <<
((result == SUCCESS) ? "SUCCESS" : "FAIL") << ::std::endl;
}
Note: you should throw only what derives from ::std::exception, but I used const char* to simplify things and prepare working example.
Since you are coding in C++, not in C, the option of throwing exceptions is available to you. Making the code look better while responding to exceptional situations properly was the primary driving force behind the feature.
In situations when you use third-party APIs that do not offer exceptions you could wrap their functions into your functions that throw exceptions, like this:
void func1w(...) {
if (SUCCESS!=func1(...)) throw my_exception();
}
void func2w(...) {
if (SUCCESS!=func2(...)) throw my_exception();
}
...
void caller() {
try {
func1w();
func2w();
func3w();
} catch (my_exception& e) {
cerr << "Error!" << endl;
}
}
Note that the function that calls exception-throwing wrappers could stay away from checking exception codes altogether, letting the higher-level function deal with them. The general rule with exceptions is that the code should not catch exceptions unless it knows how to handle them.
You can also define a macro:
#define MUST_SUCCEED(x) if(SUCCESS!=(x))return ERROR
This comes at the cost of reduced readability, because the macro is not instantly familiar to the readers of your code:
MUST_SUCCEED(func1(...));
MUST_SUCCEED(func2(...));
MUST_SUCCEED(func3(...));
Short answer: no
Long answer: no, that's how you do it in every structured programming language that I'm aware of.
Alternative: if all functions involved (func1, func2, func3) would throw exceptions instead of returning a status code then you wouldn't have to use ifs. Your function func would just propagate any exception that was thrown from within it.
Edit, expanding on Tony's comment:
Alternative #2: involved functions do not throw exceptions, but your function could. Suppose you have a helper function like this:
void CheckResult(Result result)
{
if (result != SUCCESS)
throw SomeException(result);
}
Your function would then look like this:
void func(...)
{
CheckResult(func1(...));
// do something
CheckResult(func2(...));
// do something else
CheckResult(func3(...));
// do something
}
So, the if's are not avoided but moved to another function, so that your function is free of them.
You could make a vector of function pointers containing func1(), func2() etc., then iterate through all the elements in this vector by means of for loop, calling each function and comparing the value returned against SUCCESS. Then, if the return value of any function does not equal SUCCESS, you can set a flag to a value indicating error (in your example this flag would be of the name 'result').

Catch Multiple Custom Exceptions? - C++

I'm a student in my first C++ programming class, and I'm working on a project where we have to create multiple custom exception classes, and then in one of our event handlers, use a try/catch block to handle them appropriately.
My question is: How do I catch my multiple custom exceptions in my try/catch block? GetMessage() is a custom method in my exception classes that returns the exception explanation as a std::string. Below I've included all the relevant code from my project.
Thanks for your help!
try/catch block
// This is in one of my event handlers, newEnd is a wxTextCtrl
try {
first.ValidateData();
newEndT = first.ComputeEndTime();
*newEnd << newEndT;
}
catch (// don't know what do to here) {
wxMessageBox(_(e.GetMessage()),
_("Something Went Wrong!"),
wxOK | wxICON_INFORMATION, this);;
}
ValidateData() Method
void Time::ValidateData()
{
int startHours, startMins, endHours, endMins;
startHours = startTime / MINUTES_TO_HOURS;
startMins = startTime % MINUTES_TO_HOURS;
endHours = endTime / MINUTES_TO_HOURS;
endMins = endTime % MINUTES_TO_HOURS;
if (!(startHours <= HOURS_MAX && startHours >= HOURS_MIN))
throw new HourOutOfRangeException("Beginning Time Hour Out of Range!");
if (!(endHours <= HOURS_MAX && endHours >= HOURS_MIN))
throw new HourOutOfRangeException("Ending Time Hour Out of Range!");
if (!(startMins <= MINUTE_MAX && startMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Starting Time Minute Out of Range!");
if (!(endMins <= MINUTE_MAX && endMins >= MINUTE_MIN))
throw new MinuteOutOfRangeException("Ending Time Minute Out of Range!");
if(!(timeDifference <= P_MAX && timeDifference >= P_MIN))
throw new PercentageOutOfRangeException("Percentage Change Out of Range!");
if (!(startTime < endTime))
throw new StartEndException("Start Time Cannot Be Less Than End Time!");
}
Just one of my custom exception classes, the others have the same structure as this one
class HourOutOfRangeException
{
public:
// param constructor
// initializes message to passed paramater
// preconditions - param will be a string
// postconditions - message will be initialized
// params a string
// no return type
HourOutOfRangeException(string pMessage) : message(pMessage) {}
// GetMessage is getter for var message
// params none
// preconditions - none
// postconditions - none
// returns string
string GetMessage() { return message; }
// destructor
~HourOutOfRangeException() {}
private:
string message;
};
If you have multiple exception types, and assuming there's a hierarchy of exceptions (and all derived publicly from some subclass of std::exception,) start from the most specific and continue to more general:
try
{
// throws something
}
catch ( const MostSpecificException& e )
{
// handle custom exception
}
catch ( const LessSpecificException& e )
{
// handle custom exception
}
catch ( const std::exception& e )
{
// standard exceptions
}
catch ( ... )
{
// everything else
}
On the other hand, if you are interested in just the error message - throw same exception, say std::runtime_error with different messages, and then catch that:
try
{
// code throws some subclass of std::exception
}
catch ( const std::exception& e )
{
std::cerr << "ERROR: " << e.what() << std::endl;
}
Also remember - throw by value, catch by [const] reference.
You should create a base exception class and have all of your specific exceptions derive from it:
class BaseException { };
class HourOutOfRangeException : public BaseException { };
class MinuteOutOfRangeException : public BaseException { };
You can then catch all of them in a single catch block:
catch (const BaseException& e) { }
If you want to be able to call GetMessage, you'll need to either:
place that logic into BaseException, or
make GetMessage a virtual member function in BaseException and override it in each of the derived exception classes.
You might also consider having your exceptions derive from one of the standard library exceptions, like std::runtime_error and use the idiomatic what() member function instead of GetMessage().
Another way to solve this problem when you don't have control on the class hierarchy of the exceptions and that you can't duplicate the contents of the catch block is using dynamic_cast Like this:
try
{
...
}
catch (std::exception& e)
{
if( nullptr == dynamic_cast<exception_type_1*> (&e)
&& nullptr == dynamic_cast<exception_type_2*> (&e))
{
throw;
}
// here you process the expected exception types
}
When templates can't, macros save the day.
The solution is taken from Boost. It boils to 7 lines of code.
/// #file multicatch.hpp
#include <boost/preprocessor/variadic/to_list.hpp>
#include <boost/preprocessor/list/for_each.hpp>
/// Callers must define CATCH_BODY(err) to handle the error,
/// they can redefine the CATCH itself, but it is not as convenient.
#define CATCH(R, _, T) \
catch (T & err) { \
CATCH_BODY(err) \
}
/// Generates catches for multiple exception types
/// with the same error handling body.
#define MULTICATCH(...) \
BOOST_PP_LIST_FOR_EACH(CATCH, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
// end of file multicatch.hpp
/// #file app.cc
#include "multicatch.hpp"
// Contrived example.
/// Supply the error handling logic.
#define CATCH_BODY(err) \
log() << "External failure: " << err.what(); \
throw;
void foo() {
try {
bar(); // May throw three or more sibling or unrelated exceptions.
}
MULTICATCH(IOError, OutOfMemory)
}
#undef CATCH_BODY
Derive all of your exceptions from a common base class BaseException that has a virtual method GetMessage().
Then catch(const BaseException& e).
I had a similar problem today, but it turned out I didn't need my solution to solve my problem. Honestly, I couldn't think of real use cases (logging?), and I didn't find much use for it in my code.
Anyway, this is an approach with type lists (requires C++11). I think the advantage of this approach is that there's no need to have a common base class for custom exceptions (except for std::exception, maybe?). In other words, it is not intrusive to your exception hierarchy.
There might be some subtle errors that I am not aware of.
#include <type_traits>
#include <exception>
/// Helper class to handle multiple specific exception types
/// in cases when inheritance based approach would catch exceptions
/// that are not meant to be caught.
///
/// If the body of exception handling code is the same
/// for several exceptions,
/// these exceptions can be joined into one catch.
///
/// Only message data of the caught exception is provided.
///
/// #tparam T Exception types.
/// #tparam Ts At least one more exception type is required.
template <class T, class... Ts>
class MultiCatch;
/// Terminal case that holds the message.
/// ``void`` needs to be given as terminal explicitly.
template <>
class MultiCatch<void> {
protected:
explicit MultiCatch(const char* err_msg) : msg(err_msg) {}
const char* msg;
};
template <class T, class... Ts>
class MultiCatch : public MultiCatch<Ts...> {
static_assert(std::is_base_of<std::exception, T>::value, "Not an exception");
public:
using MultiCatch<Ts...>::MultiCatch;
/// Implicit conversion from the guest exception.
MultiCatch(const T& error) : MultiCatch<Ts...>(error.what()) {} // NOLINT
/// #returns The message of the original exception.
const char* what() const noexcept {
return MultiCatch<void>::msg;
}
};
/// To avoid explicit ``void`` in the type list.
template <class... Ts>
using OneOf = MultiCatch<Ts..., void>;
/// Contrived example.
void foo() {
try {
bar(); // May throw three or more sibling or unrelated exceptions.
} catch (const OneOf<IOError, OutOfMemory>& err) {
log() << "External failure: " << err.what();
throw; // Throw the original exception.
}
}
I run into the same problem and here is what I ended up with:
std::shared_ptr<MappedImage> MappedImage::get(const std::string & image_dir,
const std::string & name,
const Packet::Checksum & checksum) {
try {
return std::shared_ptr<MappedImage>(images_.at(checksum));
} catch (std::out_of_range) {
} catch (std::bad_weak_ptr) {
}
std::shared_ptr<MappedImage> img =
std::make_shared<MappedImage>(image_dir, name, checksum);
images_[checksum_] = img;
return img;
}
In my case the function returns when it doesn't get an exception. So I don't actually have to do anything inside the catch but can do the work outside the try.
#include <iostream>
void test(int x)`
{
try{
if(x==1)
throw (1);
else if(x==2)
throw (2.0);
}
catch(int a)
{
cout<<"It's Integer";
}
catch(double b)
{
cout<<"it's Double";
}
}
int main(){
cout<<" x=1";
test(1);
cout<<"X=2";
test(2.0);
return 0;
}`