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