"Nothing can go wrong with this function and I can assume it's 100%
reliable"
I wouldn't really assume that so quickly. Typically if I see a function marked as noexcept
, I'd tend to look for alternative ways it could give me errors like a boolean state, some kind of global error retrieval function, a success/fail return value, something like that. Only lacking that, and perhaps in the face of a function that causes no side effects, might I sort of make this assumption.
In your case, you got the whole error code kind of thing going for the function, so clearly one glance at the interface documentation should tell me that things can go wrong, yet the noexcept
suggests to me that these exceptional cases won't (or at least shouldn't) be reported to me (the caller) in the form of an exception.
Applying noexcept
It seems generally on the safe side to be reluctant to use noexcept
. A single introduction of, say, std::string
to that function and now it can throw, only the noexcept
will turn that into a termination rather than something we can catch. Guaranteeing that a function will never throw at the interface/design level is a hard one to ensure in anything which actually mixes C++ code, especially in a team setting where any random colleague might introduce (maybe on a crunch day) some random C++ function call or object which can throw to this function.
Impossible to Throw
In some cases it's actually easy to make this guarantee. One example is a noexcept
function which has its own try/catch
block, where everything the function does is contained within. If an exception is caught, translate it into an error code of some sort and return that. In those cases, the try/catch
guarantees that the function will swallow the exception and not leak it to the outside world. It becomes easy to apply noexcept
here because the function can't throw.
Can't Possibly Throw Correctly
Another example of where noexcept
doesn't require too much thought is in the case of a function that should be considered broken if it threw. An example is an API function which is called across module boundaries for an SDK designed to allow plugins to be built with any compiler. Since we shouldn't throw across module boundaries, and especially in this scenario, throwing would already be UB and shouldn't be done. In that case, noexcept
can be easy to apply because the correct behavior of the function, by design, should never throw.
If in doubt, leave it out.
In your case, if in doubt, I'd suggest to leave it out. You can go a lot more wrong by using noexcept
and inadvertently throwing out of the function and terminating the program. An exception is if you can make a hard guarantee that this ClearTheBin
function is always going to be using only C, no operator new
(or at least only nothrow
versions), no dynamic_casts
, no standard lib, etc. Omission seems like erring on the safe side, unless you can make this kind of hard interface-level guarantee for both present and future.