When writing exception safe code, it is necessary to consider the exception safety guarantee (none, basic, strong or no-throw) of all the functions called. Since the compiler offers no help, I was thinking that a function naming convention might be helpful here. Is there any kind of established notational standard indicating the level of exception safety guarantee offered by functions? I was thinking along the lines of something hungarian-like:
void setFooB(Foo const& s); // B, offers basic guarantee
int computeSomethingS(); // S, offers strong guarantee
int getDataNT() throws(); // NT, offers no-throw
void allBetsAreOffN(); // N, offers no guarantee
Edit: I agree with comments that this kind of naming convention is ugly, so allow me to elaborate on my reasons for suggesting in.
Say I refactor some code, and in that process, change the level of exception safety offered by a function. If the guarantee has changed from, say, strong to basic (justified perhaps by improvement in speed), then every function that calls the refactored function must be reconsidered for their exception safety. If the change in guarantee triggered a change in the function name as well, it would allow the compiler to help me out a little bit in at least flagging all uses of the changed function. This was my rationale for suggesting the naming convention above, problematic as it is. This is very similar to const, where a change in the const-ness of a function has cascading effects on other calling functions, but in that situation the compiler gives very effective assistance.
So I guess my question is, what kind of work habits have people developed in order to ensure that code actually fullfills their intended exception guarantees, especially during code maintenance and refactoring.
I usually find myself documenting that in comments (doxygen), excepts the no throw guarantee, that I often tag with the throw()
exception specification if and only when sure that the function is guaranteed not to throw, and exception safety is important.
That is, I usually worry more about exceptions in parts of the code where an unhandled exception would cause problems, and deal with that locally (ensure that your code is exception safe by other means, as RAII, performing the work outside and then merging the results with a no throw operation --i.e. no throw swap, which is about the only function that I actively mark as throw()
.
Other people might have other experiences, but I find that to be sufficient for my daily work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With