Re: Is there a good use case for noexcept?
On 04/13/2011 11:02 PM, restor wrote:
What I call is a simple guideline how to use noexcept. Preferably one
that could fit into an item in the next More Effective C++ by Scott
Meyers or C++ Coding Standards by Sutter& Alexandrescu.
One questions I have is; which one (or several) of these apply?
1. Always use noexcept with functions that you think won't throw.
2. Always use noexcept with functions that you think won't throw or that
very very rarely throw, like for instance std::bad_alloc.
3. Only use noexcept when you really need, e.g. when you want to provide
Abrahams' exception safety guarantees.
4. Only use noexcept when you have stepped through your function, line
by line, and made sure no exception is thrown.
I believe, it would be (3), with the annotation "DO NOT USE noexcept
EXPLICITLY". Really. This is not ironical.
[...]
1 and 2 from your list would not be good candidates and neither would
4, for the following reasons.
The fact that you can prove your function never throws an exception,
does not mean that it won't throw in the future.
suppose you have function:
void swap_potinters( int * lhs, int * rhs ) noexcept
{
int * tmp = lhs;
lhs = rhs;
rhs = tmp;
}
Now, suppose you need to add logging only for the time of debugging
void swap_potinters( int * lhs, int * rhs ) noexcept
{
LOG("swapping pointers");
int * tmp = lhs;
lhs = rhs;
rhs = tmp;
}
You get an error. A throwing function declared noexcept. You want to
remove noexcept now? This will require the recompilation of the entire
program.
It's a good example. But consider this; we are going into a new era of
making our applications even more robust than ever by means of noexcept
the way Abrahams' proposed (originating from his exception safety
guarantees). We have to rethink our new designs.
So how would I solve the above problem? I would reason like this; LOG
has nothing to do with swapping pointers, so it must not effect my
decision to use noexcept. Nevertheless, we want LOG to be there.
If I had the source code to LOG then I would make LOG noexcept as well.
If I did not have the source code I would do like this
void swap_pointers( int * lhs, int * rhs ) noexcept
{
try { LOG("swapping pointers"); }
catch( ... ) {}
int * tmp = lhs;
lhs = rhs;
rhs = tmp;
}
or, if LOG is a C function we know won't throw, use the noexcept block
that Martin B. talks about in the previous post "History and evolution
of the noexcept proposal?"
void swap_pointers( int * lhs, int * rhs ) noexcept
{
noexcept { LOG("swapping pointers"); }
int * tmp = lhs;
lhs = rhs;
rhs = tmp;
}
Now, many of you may rage over my choice to swallow the exceptions from
LOG with try/catch(...){}, but remember; LOG is *not* part of the
semantics of swap_pointers, hence, that's a legal design decision.
I find this discussion very productive. We must be clear on how to
reason when using noexcept. Please feel free to provide more arguments.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]