Boost logo

Boost :

From: Gavin Lambert (boost_at_[hidden])
Date: 2019-05-27 23:57:52


On 28/05/2019 02:28, JeanHeyd Meneide wrote:
> Regarding destructors: yes. In the standard library, we have implicit
> noexcept on destructors. This inherits that same noexcept guarantee and is
> how it is implemented both here and (soon) in the Standard, pending LWG
> approval. unique_ptr has a noexcept .reset(); shared_ptr does not (control
> block allocation may fail, etc.). However, other RAII types that wrap
> objects and call non-noexcept functions are marked noexcept themselves:
> e.g., lock_guard which calls mutex.unlock
> <https://en.cppreference.com/w/cpp/thread/mutex/unlock>.

lock_guard is a "true" RAII type, though, and mutex unlock is an
"destruction type" operation that should never actually fail even if the
method was not explicitly marked noexcept. (Especially when interacting
with legacy mutex types that might not indicate noexcept behaviour.)

out_ptr is *not* an RAII type and its destructor has "non-destructive"
side effects that are known to invoke memory allocation and
construction, which are both exception-prone operations. I think it
makes the most sense to declare it noexcept(false).

Or possibly conditional noexcept on all the operations performed, so
that as you say above, it would be noexcept for unique_ptr and not for
shared_ptr.

It's probably also worth adding to the caveats that the smart pointer
must always be declared before and outside of the full-expression that
contains the out_ptr. (While you'd normally expect this in order to
achieve useful variable lifetime scoping, it would probably be possible
to construct an example that does this incorrectly.) If they're in the
same expression then it might be possible for the compiler to destroy
the smart pointer before destroying the out_ptr, and then hilarity will
ensue.

Regarding the "poorly designed C APIs" caveat: some APIs guarantee that
they do not alter the value of output parameters on failure. So you
definitely should not assume that the value is always set to nullptr on
failure; at least for out_ptr you should be passing in a raw pointer
that is already nullptr, not uninitialised or some other value. If
you're not doing that, the bug is in your library, not in the API.
(Your caveat is correct for inout_ptr, however.)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk