www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Any way to create derived classes from Exception with canned messages?

reply Jeremy T. Gibson <jtgibson telus.net> writes:
Is there any way to go about making derived Exception classes 
which produce a passed error message plus a hard-coded annotation 
string provided by the derived class, allowing me to use both a 
consistent error message suffix plus a programmer-specified error 
message?

I'm running into a problem where I want to create a set of 
Exception classes that automatically annotate Exception calls 
based on the class of the Exception, ensuring a more rigid 
syntax, avoiding typos and/or having to remember to identify the .

In my (barebones) production code, I currently have:

     throw new Exception("vec3.bearing (NotYetImplemented)");

but I would vastly prefer that to be:

     throw new NotYetImplementedException("vec3.bearing");

which offers code completion, typo safety, consistency, a toolbox 
of recommended exception types if I ever stop being the sole 
programmer, etc.  (Still nothing I can do to pull the name of the 
current function and include that automatically (I think?), since 
the best I've got is `__LINE__` etc.  But we can't all eat *pure* 
syntactic sugar or we'd die of code-abetes.)

Now, https://github.com/dlang/druntime/blob/master/src/object.d 
clearly expresses that the constructors of Exception are  nogc.  
Therein lies the problem: there is no way to use the ~ 
concatenation operator in a  nogc function.  At least at my 

where this is trivial), I can't think of any other way to pass a 
pure/nogc pair of strings that won't trip up the safety 
parameters.

Just as a raw test case, I tried the following:

https://run.dlang.io/is/VmCKwV

(where classes derived from MyException would then override the 
annotation function accordingly, avoiding the  safe limitation of 
global/static variables) and, sure enough, it didn't work -- as I 
anticipated it wouldn't.

I do get the reason why the Exception class is  nogc, as you 
can't necessarily rely on the memory state when an Exception is 
thrown.  If it wasn't memory-safe, it would be possible to enter 
a state where the Exception explaining why the program is failing 
won't be produced when the program fails because it too fails, 
making it even harder to figure out the problem.  But given that 
the substantial majority of manually thrown exceptions *do* 
consist of program states that aren't out of memory, it also 
limits my usage case.

I'm going to be digging around Phobos to see if I can mishmash 
something out of the stringizing functions, but that seems 
convoluted when a string concatenation "intuitively" should work, 
even though it obviously doesn't.

Has anyone else worked through this problem before and come up 
with a more elegant solution?  Am I just over-analyzing the 
problem?
Jul 31 2021
next sibling parent jfondren <julian.fondren gmail.com> writes:
On Saturday, 31 July 2021 at 08:25:56 UTC, Jeremy T. Gibson wrote:
 Now, https://github.com/dlang/druntime/blob/master/src/object.d 
 clearly expresses that the constructors of Exception are  nogc. 
  Therein lies the problem: there is no way to use the ~ 
 concatenation operator in a  nogc function.  At least at my 

 where this is trivial), I can't think of any other way to pass 
 a pure/nogc pair of strings that won't trip up the safety 
 parameters.

 Just as a raw test case, I tried the following:

 https://run.dlang.io/is/VmCKwV
`annotation()` should also be nothrow as it's called by the nothrow constructor. https://run.dlang.io/is/OBNfxq use a limited nogc string formatter from dub, with an instance buffer. https://run.dlang.io/is/Osoiyd for such a simple format, do it manually. require the caller to call a non- nogc function which can build a string and then throw/return a constructed exception.
Jul 31 2021
prev sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 31 July 2021 at 08:25:56 UTC, Jeremy T. Gibson wrote:
 Now, https://github.com/dlang/druntime/blob/master/src/object.d 
 clearly expresses that the constructors of Exception are  nogc.
That doesn't mean your constructors have to be! You can do whatever you want. Constructors aren't an inherited interface.
Jul 31 2021
next sibling parent Adam D Ruppe <destructionator gmail.com> writes:
I'll add just for info sake even though you can just use normal 
gc in your own constructors as wanted, other options include:

1) making a buffer inside your new object and copying the message 
to it, then passing a slice of your buffer to the super ctor.

2) making all the messages compile-time literals so each class 
has a static message. then there's no runtime work at all. (and 
you can differentiate things based on type!)

can even be defined inline like

`throw new NotImplemented!"thing"`

and then the impl is like

class NotImplementedBase : Exception {
   mixin ExceptionCtors;
}

class NotImplemented(string msg) : NotImplmentedntedBase {
    this() { super ("Not implemented" ~ msg); }
}


that kind of thing just plus the file line info etc too arguments.

3) ignore hte msg member and just override toString



But again the base ctor limitations do NOT apply to derived 
classes so it is all moot.


btw for virtual interfaces base things do apply but you're 
allowed to tighten if you want. so like base toString is NOT 
 nogc but if you wanted derived  nogc that's perfectly allowed. 
virtual methods must be as strict or stricter since they're 
inherited. just again ctors are not inherited so there's no 
connection at all.
Jul 31 2021
prev sibling parent Jeremy T. Gibson <jtgibson telus.net> writes:
On Saturday, 31 July 2021 at 11:30:06 UTC, Adam D Ruppe wrote:
 On Saturday, 31 July 2021 at 08:25:56 UTC, Jeremy T. Gibson 
 wrote:
 Now, 
 https://github.com/dlang/druntime/blob/master/src/object.d 
 clearly expresses that the constructors of Exception are  nogc.
That doesn't mean your constructors have to be! You can do whatever you want. Constructors aren't an inherited interface.
Hah! I knew it was something simple. I should have guessed, when I was being shouted at when I tried to use the "override" keyword (obviously they're not virtual either), that I was approaching it all wrong.
Jul 31 2021