Sub-classing exceptions
Shriramana Sharma via Digitalmars-d
digitalmars-d at puremagic.com
Thu Oct 15 11:07:19 PDT 2015
In Python I can create my own thin exceptions (i.e. just different type for
convenience of identification in a catch block, no added functionality) by:
class MyError(ExceptionBaseClass): pass
Even in C++ I can do just:
struct MyException: public std::exception {};
But in D:
$ cat except.d
class MyException: Exception {}
$ dmd -c except.d
except.d(1): Error: class foo.MyException cannot implicitly generate a
default ctor when base class object.Exception is missing a default ctor
OK so I dig up /usr/include/dmd/druntime/import/object.d: which doesn't have
a default ctor but does have a user-defined one, which then disables the
default:
class Exception : Throwable
{
@nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t
line = __LINE__, Throwable next = null)
}
OK fine but then I didn't get why I had to write that long constructor with
msg, file, __FILE__ etc every time I subclassed exception, so I did:
$ cat except.d
class MyException: Exception { this() { super(""); } }
void main() { throw new MyException; }
But it didn't give the expected results:
$ dmd except.d
$ ./except
except.MyException at except.d(1)
...
... since the line number is wrong. OK so the reason is that the constructor
which has the default arguments of __FILE__ and __LINE__ is called not at
line 2 but at line 1 i.e. in the declaration of the subclass.
So I am forced to write out all that stuff with __FILE__ etc yet again:
$ cat except.d
class MyException: Exception { this(string msg = "", string file = __FILE__,
size_t line = __LINE__) { super("", file, line); } }
void main() { throw new MyException; }
Then I get the desired behaviour:
$ dmd except.d
$ ./except
except.MyException at except.d(2)
This is too tortuous, and methinks a mixin is in order, and since I can't do
anything like the C preprocessor's #X stringizing, I can't declare this as a
mixin template but have to do a string mixin:
$ cat myexception.d
string ExceptionDeclaration(string newExceptionName, string
baseExceptionName = "Exception")
{
return "class " ~ newExceptionName ~ ": " ~ baseExceptionName ~ `{
this(string msg = "", string file = __FILE__, size_t line =
__LINE__)
{ super(msg, file, line); }
}`;
}
void main()
{
mixin(ExceptionDeclaration("MeaCulpa"));
try { throw new MeaCulpa; }
catch (MeaCulpa e) {}
import std.conv;
mixin(ExceptionDeclaration("MeaNeueaCulpa", "ConvException"));
try { throw new MeaNeueaCulpa; }
catch (MeaNeueaCulpa e) {}
throw new MeaNeueaCulpa;
}
$ dmd myexception.d
$ ./myexception
myexception.main.MeaNeueaCulpa at myexception.d(18)
...
So, any thoughts? Any way this could be improved? Would be nice if that
mixin got into the standard library somehow...
More information about the Digitalmars-d
mailing list