Catching std::exception and ERROR_STATUS - c++

In my code I use my defined BasicException
enum class MyError {
ERROR_1,
ERROR_2
};
class BasicException
{
public:
BasicException(MyError err): _err(err) {}
get_error() const {return _err;}
private:
MyError _err;
}
The problem is that I was told that BasicException should inherit from std::exception. But then, When I will catch (const std::exception& e) I won't be able to retrieve the MyError of the specific error. So what good is in it?
I'm not sure what will be the optimal solution - But maybe if std::exception had a constructor that receives error value it would solve it.

If you want to specifically catch BasicException, catch it first like this :
try
{
}
catch( BasicException& be )
{
// your exception here
}
catch( std::exception& e )
{
// other exceptions here
}
And if you want to catch all exception including yours ( if BasicException inherit of std::exception ), then :
try
{
}
catch( std::exception& e )
{
// all exceptions here
}

Related

Passing message in std::exception from managed code to unmanaged

I am trying to throw a std::exception from managed code so that it is caught in unmanaged code. Where I'm struggling is passing a string (describing the exception) so that the (re-)caught exception can be examined using the what() method ...
#pragma managed
static std::string InvokeMethod() {
try {
//...
}
catch (Exception^ ex) {
std::string myExMsg = msclr::interop::marshal_as<std::string>(ex->ToString());
throw std::exception(myExMsg);
}
}
#pragma unmanaged
void Execute() {
try {
myMethod = InvokeMethod();
}
catch (std::exception ex) {
SetError(ex.what());
}
}
This doesn't compile with "no instance of constructor "stdext:exceptipon::exception" matches the argument list argument types are (std::string)" BUT if I 'hard code' a string into std::exception like this ...
throw std::exception("An error has occurred");
... then that string gets passed along and returned by ex.what(). I also tried ...
throw std::runtime_error(myExMsg);
... but ex.what() just returns a string ending with '\x7F' (in case that's a clue).
It looks to me that std::exception is expecting some other type. But what type? What does 'myExMsg' need to be so that ex.what() returns the same string (that can be used in the SetError method)?
Following suggestion made by #Joe, I inherit from std::exception ...
class InvokeException : public std::exception {
public:
InvokeException(std::string const& message) : msg_(message) { }
virtual char const* what() const noexcept { return msg_.c_str(); }
private:
std::string msg_;
};
... and then ...
const std::string myExMsg = msclr::interop::marshal_as<std::string>(ex->Message);
throw InvokeException(myExMsg);

Proper/elegant way of implementing C++ exception chaining?

I'd like to implement an Exception class in C++ that mimics the one from .NET framework (and Java has something similar too), for the following purposes:
Exception chaining: I'd like to implement the concept of "exception translation", when exceptions caught at higher levels wrap and "translate" the lower level exceptions, also preserving these lower-level exceptions somehow (in the InnerException member, in this case). For this, there should be some mechanism to store inner exceptions along with each exception thrown at the upper level. InnerException member provides this in the implementation below.
Exception inheritance: there should be possible to derive IoException from Exception, and SerialPortException from IoException, for example. While this seems trivial, there should be ability to identify the type of caught exceptions dynamically (e.g. for logging purposes, or to display to user), preferably without the overhead of RTTI and typeid.
This is the sample exception handling logic I'd like to make possible:
try
{
try
{
try
{
throw ThirdException(L"this should be ThirdException");
}
catch(Exception &ex)
{
throw SubException(L"this should be SubException", ex);
}
}
catch(Exception &ex)
{
throw SubException(L"this should be SubException again", ex);
}
}
catch(Exception &ex)
{
throw Exception(L"and this should be Exception", ex);
}
and when catching the "outer-most" exception in the upmost layer I'd like to be able to parse and format whole exception chain through the InnerException member, to display something like this:
I've come up with the following implementation so far:
Small note: CString is Microsoft-specific string class (just for the people not familiar with Visual C++ stuff).
class Exception
{
protected:
Exception(const Exception&) {};
Exception& operator= (const Exception&) {};
public:
Exception(const CString &message) : InnerException(0), Message(message) {}
Exception(const CString &message, const Exception &innerException) : InnerException(innerException.Clone()), Message(message) {}
virtual CString GetExceptionName() const { return L"Exception"; }
virtual Exception *Clone() const
{
Exception *ex = new Exception(this->Message);
ex->InnerException = this->InnerException ? this->InnerException->Clone() : 0;
return ex;
}
public:
virtual ~Exception() { if (InnerException) delete InnerException; }
CString Message;
const Exception *InnerException;
};
Now what do we have here. Copy constructor and assignment operator are made protected to prevent copying. Each object will "own" its inner exception object (and delete it in destructor), so default shallow-copying would be unacceptable. Then we have two pretty standard-looking constructors and virtual destructor that deletes the InnerException object. Clone() virtual method is responsible for deep-copying the objects, primarily for storing the inner exception object (see the second constructor). And finally GetExceptionName() virtual method provides the cheap alternative to RTTI for identification of exception class names (I don't think this looks cool but I couldn't come up with better solution; for comparison: in .NET one could simply use someException.GetType().Name).
Now this does the job. But... I don't like this solution for one particular reason: the amount of coding needed for each derived class. Consider I have to derive SubException class, which provides absolutely zero additions to the base class functionality, it just provides the custom name ("SubException", which might be "IoException", "ProjectException", ...) to differentiate it for its usage scenario. I have to provide almost same amount of code for each of such exception class. Here it is:
class SubException : public Exception
{
protected:
SubException(const SubException& source) : Exception(source) {};
SubException& operator= (const SubException&) {};
public:
SubException(const CString &message) : Exception(message) {};
SubException(const CString &message, const Exception &innerException) : Exception(message, innerException) {};
virtual CString GetExceptionName() const { return L"SubException"; }
virtual Exception *Clone() const
{
SubException *ex = new SubException(this->Message);
ex->InnerException = this->InnerException ? this->InnerException->Clone() : 0;
return ex;
}
};
I don't like the fact that I have to provide protected copy constructor and assignment operator each time, I don't like the fact that I have to clone the Clone method each time, duplicating even the code of copying the base members (InnerException...), simply... I don't think this is the elegant solution. But I was unable to think of better one. Do you have any ideas how to implement this concept "properly"? Or maybe this is the best implementation of this concept that is possible in C++? Or maybe I'm doing this completely wrong?
P.S.: I know there exist some mechanisms in C++11 (also in Boost) for this purpose (exception chaining) with some new exception classes, but I'm primarily interested in custom, "old-C++-compatible" ways. But it would be good, in addition, if someone could provide any code in C++11 that accomplishes the same.
C++11 already has nested_exception. There was a talk about exceptions in C++03 and C++11 at Boostcon/C++Next 2012. Videos are on youtube:
http://www.youtube.com/watch?v=N9bR0ztmmEQ&feature=plcp
http://www.youtube.com/watch?v=UiZfODgB-Oc&feature=plcp
There is a lot of extra code, but the good thing is it's really EASY extra code that doesn't change at all from class to class, so it's possible to preprocessor macro it.
#define SUB_EXCEPTION(ClassName, BaseName) \
class ClassName : public BaseName\
{\
protected:\
\
ClassName(const ClassName& source) : BaseName(source) {};\
ClassName& operator= (const ClassName&) {};\
\
public:\
\
ClassName(const CString &message) : BaseName(message) {};\
ClassName(const CString &message, const BaseName &innerException) : BaseName(message, innerException) {};\
\
virtual CString GetExceptionName() const { return L"ClassName"; }\
\
virtual BaseName *Clone() const\
{\
ClassName *ex = new ClassName(this->Message);\
ex->InnerException = this->InnerException ? this->InnerException->Clone() : 0;\
return ex;\
}\
};
Then you can define various utility exceptions by just doing:
SUB_EXCEPTION(IoException, Exception);
SUB_EXCEPTION(SerialPortException, IoException);
Please don't follow boost::exception approach. Boost::exception is for different use case - in particular it's usefull when you want to collect precise exception context scatered over call stack. Consider the following example:
#include "TSTException.hpp"
struct DerivedException: TST::Exception {};
int main() try
{
try
{
try
{
try
{
throw std::runtime_error("initial exception");
}
catch(...)
{
throw TST::Exception("chaining without context info");
}
}
catch(...)
{
TST_THROW("hello world" << '!');
}
}
catch(...)
{
TST_THROW_EX(DerivedException, "another exception");
}
}
catch(const TST::Exception& ex)
{
cout << "diagnostics():\n" << ex;
}
catch(const std::exception& ex)
{
cout << "what(): " << ex.what() << endl;
}
The "exception chaining" solution as I understand it should produce output similar to this:
$ ./test
diagnostics():
Exception: another exception raised from [function: int main() at main.cpp:220]
Exception: hello world! raised from [function: int main() at main.cpp:215]
Exception: chaining without context info raised from [function: unknown_function at unknown_file:0]
Exception: initial exception
As you see there are exceptions chained to each other and diagnostic output contains all exceptions with context information and optional stack trace (not shown here, because it's compiler/platform dependent).
"Exception chaining" can be naturally achieved using new C++11 error handling features (std::current_exception or std::nested_exception). Here is implementation of TSTException.hpp (please bear with more source code):
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <exception>
#include <vector>
#include <string>
#include <memory>
#include <boost/current_function.hpp>
#include <boost/foreach.hpp>
using namespace std;
namespace TST
{
class Exception: virtual public std::exception
{
public:
class Context
{
public:
Context():
file_("unknown_file"),
line_(0),
function_("unknown_function")
{}
Context(const char* file, int line, const char* function):
file_(file? file: "unknown_file"),
line_(line),
function_(function? function: "unknown_function")
{}
const char* file() const { return file_; }
int line() const { return line_; }
const char* function() const { return function_; }
private:
const char* file_;
int line_;
const char* function_;
};
typedef std::vector<std::string> Stacktrace;
//...
Exception()
{
initStacktraceAndNestedException();
}
explicit Exception(const std::string& message, const Context&& context = Context()):
message_(message),
context_(context)
{
message.c_str();
initStacktraceAndNestedException();
}
~Exception() throw() {}
//...
void setContext(const Context& context) { context_ = context; }
void setMessage(const std::string& message) { (message_ = message).c_str(); }
const char* what() const throw () { return message_.c_str(); }
void diagnostics(std::ostream& os) const;
protected:
const Context& context() const { return context_; }
const std::exception_ptr& nested() const { return nested_; }
const std::shared_ptr<Stacktrace>& stacktrace() const { return stacktrace_; }
const std::string& message() const { return message_; }
private:
void initStacktraceAndNestedException();
void printStacktrace(std::ostream& os) const;
std::string message_;
Context context_;
std::shared_ptr<Stacktrace> stacktrace_;
std::exception_ptr nested_;
};
std::ostream& operator<<(std::ostream& os, const Exception& ex)
{
ex.diagnostics(os);
return os;
}
std::ostream& operator<<(std::ostream& os, const Exception::Context& context)
{
return os << "[function: " << context.function()
<< " at " << context.file() << ':' << context.line() << ']';
}
void Exception::diagnostics(std::ostream& os) const
{
os << "Exception: " << what() << " raised from " << context_ << '\n';
if (const bool haveNestedException = nested_ != std::exception_ptr())
{
try
{
std::rethrow_exception(nested_);
}
catch(const TST::Exception& ex)
{
if(stacktrace_ && !ex.stacktrace())//if nested exception doesn't have stacktrace then we print what we have here
printStacktrace(os);
os << ex;
}
catch(const std::exception& ex)
{
if(stacktrace_)
printStacktrace(os);
os << "Exception: " << ex.what() << '\n';
}
catch(...)
{
if(stacktrace_)
printStacktrace(os);
os << "Unknown exception\n";
}
}
else if(stacktrace_)
{
printStacktrace(os);
}
}
void Exception::printStacktrace(std::ostream& os) const
{
if(!stacktrace_)
{
os << "No stack trace\n";
return;
}
os << "Stack trace:";
BOOST_FOREACH(const auto& frame, *stacktrace_)
{
os << '\n' << frame;
}
os << '\n';
}
void Exception::initStacktraceAndNestedException()
{
nested_ = std::current_exception();
if(const bool haveNestedException = nested_ != std::exception_ptr())
{
try
{
throw;
}
catch(const TST::Exception& ex)
{
if(ex.stacktrace())
{
stacktrace_ = ex.stacktrace();
return;
}
}
catch(...) {}
}
/*TODO: setStacktrace(...); */
}
}//namespace TST
#ifdef TST_THROW_EX_WITH_CONTEXT
#error "TST_THROW_EX_WITH_CONTEXT is already defined. Consider changing its name"
#endif /*TST_THROW_EX_WITH_CONTEXT*/
#define TST_THROW_EX_WITH_CONTEXT( \
CTX_FILE, CTX_LINE, CTX_FUNCTION, EXCEPTION, MESSAGE) \
do \
{ \
EXCEPTION newEx; \
{ \
std::ostringstream strm; \
strm << MESSAGE; \
newEx.setMessage(strm.str()); \
} \
newEx.setContext( \
TST::Exception::Context( \
CTX_FILE, CTX_LINE, CTX_FUNCTION)); \
throw newEx; \
} \
while(0)
#ifdef TST_THROW_EX
#error "TST_THROW_EX is already defined. Consider changing its name"
#endif /*TST_THROW_EX*/
#define TST_THROW_EX(EXCEPTION, MESSAGE) \
TST_THROW_EX_WITH_CONTEXT(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, EXCEPTION, MESSAGE)
#ifdef TST_THROW
#error "TST_THROW is already defined. Consider changing its name"
#endif /*TST_THROW*/
#define TST_THROW(MESSAGE) \
TST_THROW_EX(TST::Exception, MESSAGE)
I use compiler with partial C++11 support (gcc 4.4.7) so you can see some old style peaces of code here. Just for reference you can use the following compilation parameters to build this example (-rdynamic is for stack trace):
g++ main.cpp TSTException.hpp -rdynamic -o test -std=c++0x
Few years ago I wrote this: Unchaining Chained Exceptions in C++
Basically, the exceptions are not nested inside each other, because it would be difficult to catch the original one, but another mechanism keeps track of all the functions visited by the exception while it travels to its catch point.
A revisited version of that can be found in the library Imebra on Bitbucket, here and here.
Now I would rewrite that with some improvements (e.g. use local thread storage to keep the stack trace).
Using this approach allows you to catch the original exception that was thrown, but to still have the stack trace and possibly other information added by the functions visited by the exception while it travels back to the catch statement.

Is this way of exceptions handling good practice?

Would you change anything in this code?
class LocalPort {
public:
LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
void Open() {
try {
innerPort->Open();
}
catch (DeviceResponseException& e) {
throw PortDeviceFailure(e);
}
catch (ATM1212UnlockedException& e) {
throw PortDeviceFailure(e);
}
catch (GMXError& e) {
throw PortDeviceFailure(e);
}
}
private:
ACMEPort* innerPort;
};
/////////
try {
LocalPort* port = new LocalPort(12);
port->Open();
}
catch (bad_alloc& e) {
ReportError(e);
logger.Log("Wyjątek alokacji pamięci", e);
delete port;
}
catch (PortDeviceFailure& e) {
ReportError(e);
logger.Log(e.getMessage(), e);
delete port;
}
What I tried to above do was to make code below look and act better.
try {
ACMEPort* port = new ACMEPort(12);
port->Open();
}
catch (bad_alloc& e) {
ReportPortError(e);
logger.Log("Wyjątek alokacji pamięci", e);
delete port;
}
catch (DeviceReponseException& e) {
ReportPortError(e);
logger.Log("Wyjątek odpowiedzi urządzenia", e);
delete port;
}
catch (ATM1212UnlockedException& e) {
ReportPortError(e);
logger.Log("Wyjątek odblokowania", e);
delete port;
}
catch (GMXError& e) {
ReportPortError(e);
logger.Log("Wyjątek odpowiedzi urządzenia");
delete port;
}
catch (...) {
ReportPortError(0);
logger.Log("Wyjątek nieznanego pochodzenia");
delete port;
}
Did I succeed? Is the first better than the second? What do you think?
It seems like you have badly designed exception classes. Why don't you simply add a member-function getMessage to your exception-hierarchy (preferably in the base-class all your exceptions derive from - std::exception provides the method what that returns an error message). This way, you could simply catch all exceptions in one statement, and handle them all in the same way.
class DeviceResponseException : public std::runtime_error {
public:
DeviceResponseException() : std::runtime_error("Some error message") {}
};
class ATM1212UnlockedException : public std::runtime_error {
public:
ATM1212UnlockedException() : std::runtime_error("Some other error message") {}
};
Then in your code, you can do this:
try {
std::auto_ptr<ACMEPort> port(new ACMEPort(12));
port->Open();
}
catch( std::runtime_error & e) {
ReportPortError(e);
logger.Log(e.what(), e);
}
Since your exception-classes all derive from std::runtime_error, this catch-clause catches them all. This is OK, since the handling is the same for all cases. If you have specific exceptions that require special handling, you add additional catch-clauses.
Also, instead of calling delete port in the exception handler, you should use an std::auto_ptr or boost::scoped_ptr or something of the kind. Read about RAII.
Yes, I would:
have one single exception class and thus:
not translate exceptions from one type to another
catch the exceptions much higher up in the code and thus:
not end up writing more exception handling code than real code
and I would not create objects using new, and if I did I'd use smart pointers
Basically, I think you have completely misunderstood how exceptions should be used.
The best single change you could make to your code is to replace:
ACMEPort* port = new ACMEPort(12);
port->Open();
with:
ACMEPort port(12);
port.Open();
and similarly elsewhere - the need for catching exceptions then goes away.
I'd move the exception handlers into the class and let the class handle errors instead of forcing all callers to handle it. This way you can do clean up of the pointer (if you really have to have a pointer for some reason) by checking the result value of Open():
class LocalPort {
public:
LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
bool Open() {
try {
innerPort->Open();
return true;
}
catch (DeviceResponseException& e) {
throw PortDeviceFailure(e);
}
catch (ATM1212UnlockedException& e) {
throw PortDeviceFailure(e);
}
catch (GMXError& e) {
throw PortDeviceFailure(e);
}
catch (bad_alloc& e) {
ReportError(e);
logger.Log("Wyjątek alokacji pamięci", e);
}
catch (PortDeviceFailure& e) {
ReportError(e);
logger.Log(e.getMessage(), e);
}
return false;
}
private:
ACMEPort* innerPort;
};
LocalPort* port = new LocalPort(12);
if (!port->Open()) {
delete port;
}

Catch derived exception when returning reference of base class type?

I'm writing a windows application in C++ and encountered the following problem when working with exceptions.
I have a base exception class from which all other exceptions derive from. In the base class I have a method for the error message of any exception. That method then returns the exception (through '*this').
Now, the problem occurs when I want to extend a derived exception and later user it in a catch block. Since the extend method is declared in the base class, the catch block catches the base class instead of the derived class. Is there any way of working around this so that the correct derived class is caught instead?
Here are some code illustrating the problem:
// DECLARATIONS
class BaseException {
BaseException() { }
Exception& extend( string message ) {
// extend message
return *this;
}
}
class DerivedException : public BaseException {
DerivedException() : Exception() { }
}
// RUNNING CODE
int main() {
try {
...
try {
...
// Something goes wrong
throw DerivedException( "message1" );
}
catch ( DerivedException& exc ) {
throw exc.extend( "message2" );
}
}
catch ( DerivedException& ) {
// Here is where I *want* to land
}
}
catch ( BaseException& ) {
// Here is where I *do* land
}
}
At the moment I have "solved" it by not making the extend method virtual, but declaring it in each exception with correct return type. It works, but it's not pretty.
It would be much simpler to separate the extend() call and the re-throwing of the exception:
catch ( DerivedException& exc ) {
exc.extend( "message2" );
throw;
}
This way extend() doesn't have to return anything and always the right exceptions are thrown/caught.
This can be done using the "Curiously recurring template pattern"
template <typename TExc>
class BaseException {
BaseException() { }
TExc& extend( string message ) {
// extend message
return (TExc) *this;
}
}
class DerivedException : public BaseException<DerivedException> {
DerivedException() : BaseException() { }
}
The problem is that return type of extend is 'BaseException&'. Therefore 'throw exc.extend()' is caught in the wrong exception handler.
If you want to throw the same exception, use can use the empty throw; statement. The OP code had lots of errors.
class BaseException {
public:
BaseException() { }
BaseException& extend( string message ) {
// extend message
return *this;
}
};
class DerivedException : public BaseException {
public:
DerivedException() : BaseException() { }
};
// RUNNING CODE
int main() {
try {
try {
// Something goes wrong
throw DerivedException();
}
catch ( DerivedException& exc ) {
throw exc.extend("A");
}
}
catch ( DerivedException& ) {
// Here is where I *want* to land
int i = 0;
}
catch ( BaseException& ) {
// Here is where I *do* land
int i = 0;
}
}
You should make the extend function virtual, and return a DerivedException& in the DerivedException's override. This is legal only for special cases where the return value can be implicitly casted - such as where the original function signature returns a base class of the override function signature's return value, as I show below.
class BaseException {
public:
BaseException() { }
virtual BaseException& extend( std::string message ) {
// extend message
return *this;
}
};
class DerivedException : public BaseException {
public:
virtual DerivedException& extend( std::string message ) {
return *this;
}
DerivedException(std::string) : BaseException() { }
};
// RUNNING CODE
int main() {
try {
try {
// Something goes wrong
throw DerivedException( "message1" );
}
catch ( DerivedException& exc ) {
throw exc.extend( "message2" );
}
}
catch ( DerivedException& ) {
std::cout << "DerivedException!";
}
catch ( BaseException& ) {
std::cout << "BaseException!";
}
std::cin.get();
}
Displays DerivedException!

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;
}`