Reputation: 2096
I have a base class for exceptions:
class BaseException : public std::runtime_error
{
public:
BaseException(int Code, std::string Msg) : runtime_error(Msg);
//...etc
};
In every class that needs exceptions, I embed a Exception
class that inherits from BaseException
:
class Foo
{
public:
class Exception : public BaseException
{
public:
Exception(int Code, std::string OptMsg = "") : BaseException(Code, OptMsg);
enum
{
Fire,
Flood,
Aliens
};
};
//...etc
};
So now I can throw(Exception::Fire)
inside Foo
and catch by base class or by Foo::Exception&
and compare to Foo::Exception::Fire
for example.
The Exception
class definition is nearly identical every time tough, only the enum contents change. Because of DRY, I was thinking of writing a macro that allows something like this:
EXCEPTIONS
Fire,
Flood,
Aliens
END_EXCEPTIONS
However, macro's are frowned upon in C++. Is there a better way?
Upvotes: 2
Views: 92
Reputation: 28987
How about:
template <typename T>
struct Exception : BaseException
{
Exception(int Code, std::string OptMsg = "") : BaseException(Code, OptMsg);
};
class Foo
{
public:
using Exception = ::Exception<Foo>;
enum ExceptionCodes
{
Fire,
Flood,
Aliens
};
//...etc
};
(above unseen by a compiler)
The only difference is that you have to refer to Foo::Fire
or Foo::ExceptionCodes::Fire
.
You could do without the using
statement, and just refer to Exception<Foo>
.
Upvotes: 2
Reputation: 10393
You can "inherit" the BaseException
constructors with the using
keyword instead of manually reimplementing them. This should save you some typing. The rest of the boilerplate is pretty minimal, so I personally wouldn't worry about it.
struct Foo {
struct Exception : BaseException {
using BaseException::BaseException;
enum {
Fire,
Flood,
Aliens
};
};
};
Upvotes: 2