You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use noexcept when it makes sense for the performance (move, swap, ...) or it can be guaranteed the function will not fail.
Summary
So my take from reading more about the experiences people made with noexcept is the following.
First of all see noexcept not as a no-throw guarantee but as a no-fail guarantee. That means you can make sure that the function won't fail - so there is no need for any error handling, wether it is due to error return codes or throws. For example most of the cases comparsion operators or functions that does some arithmetic operations which won't overflow or underflow are no-fail. Then declaring them noexcept would be fine and express the intent. Especially for those who use this function in their code and need to reason about their guarantees.
Another point would be if the thing that fails is so severe that it you cannot recover from it. In this case throwing an exception does not make sense at all and calling terminate is the only sane thing to to.
Some benefits a noexcept function should bring is optimised code. There are two different kind of optimisations. First, the compiler doesn't have to do a certain amount of setup to prepare for stack unwinding in case something breaks. But as far as I can read it merely means that the code size will be reduced. But exception handling code is added to spearate parts of the code and only called when it fails so you usually do not expect runtime penalties. If you think it does than measure it to be sure.
The only important thing from a pure technical point of view is to use noexcept, when you can use it for static dispatching and call optimised functions baed on this. So far it seems that declaring move-constructors, move-assignment, destructors (which are implicitly declared noexcept as long as all member destructors or base class destructors are non-throwing) as well as swap overloads noexcept is important to activate more performant branches within the STL, e.g. when reszing a vector. In fact, this boils down to whether or not there are specific type traits to check if the functions are noexcept which can be done currently with all constructors, destructor and assignment operators and swap function.
Based on this I would argue on the following rules:
Always use noexcept for move-constructor, move-assignment, destructor and user defined swap (unless of course it can't be guaranteed)
Always use noexcept if it participates in overload dispatching to perform more optimised routines in other expressions than the ones named in 1.
Always use noexcept for function you guarantee they won't fail. (That also includes calling functions from other libraries that are not declared noexcept, for example upper_bound, but cannot throw, or if they do than something is way off and not in a recoverable state.)
Use noexcept when it in general improves compiletime/runtime but measure it to be sure.
In generic contexts where you can't be sure but merely want to preserve the state of the generic expression use the noexcept-operator, i.e. noexcept(noexcept(expr))
The text was updated successfully, but these errors were encountered:
Resources:
tl;dr
Use noexcept when it makes sense for the performance (move, swap, ...) or it can be guaranteed the function will not fail.
Summary
So my take from reading more about the experiences people made with noexcept is the following.
First of all see noexcept not as a no-throw guarantee but as a no-fail guarantee. That means you can make sure that the function won't fail - so there is no need for any error handling, wether it is due to error return codes or throws. For example most of the cases comparsion operators or functions that does some arithmetic operations which won't overflow or underflow are no-fail. Then declaring them noexcept would be fine and express the intent. Especially for those who use this function in their code and need to reason about their guarantees.
Another point would be if the thing that fails is so severe that it you cannot recover from it. In this case throwing an exception does not make sense at all and calling terminate is the only sane thing to to.
Some benefits a noexcept function should bring is optimised code. There are two different kind of optimisations. First, the compiler doesn't have to do a certain amount of setup to prepare for stack unwinding in case something breaks. But as far as I can read it merely means that the code size will be reduced. But exception handling code is added to spearate parts of the code and only called when it fails so you usually do not expect runtime penalties. If you think it does than measure it to be sure.
The only important thing from a pure technical point of view is to use noexcept, when you can use it for static dispatching and call optimised functions baed on this. So far it seems that declaring move-constructors, move-assignment, destructors (which are implicitly declared noexcept as long as all member destructors or base class destructors are non-throwing) as well as swap overloads noexcept is important to activate more performant branches within the STL, e.g. when reszing a vector. In fact, this boils down to whether or not there are specific type traits to check if the functions are noexcept which can be done currently with all constructors, destructor and assignment operators and swap function.
Based on this I would argue on the following rules:
In generic contexts where you can't be sure but merely want to preserve the state of the generic expression use the noexcept-operator, i.e.
noexcept(noexcept(expr))
The text was updated successfully, but these errors were encountered: