https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111667
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jonathan Wakely <r...@gcc.gnu.org>: https://gcc.gnu.org/g:c7f6537db94f7c6320a5a8ecaa387c9b9ce1f0ac commit r14-5524-gc7f6537db94f7c6320a5a8ecaa387c9b9ce1f0ac Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Nov 15 23:02:34 2023 +0000 libstdc++: Implement std::out_ptr and std::inout_ptr for C++23 [PR111667] This implements that changes from P1132R8, including optimized paths for std::shared_ptr and std::unique_ptr. For std::shared_ptr we pre-allocate a new control block in the std::out_ptr_t constructor so that the destructor is non-throwing. This requires some care because unlike the shared_ptr(Y*, D, A) constructor, we don't want to invoke the deleter if allocating the control block throws, because we don't own any pointer yet. In order to avoid the unwanted deleter invocation, we create the control block manually. We also want to avoid invoking the deleter on a null pointer on destruction, so we destroy the control block manually if there is no pointer to take ownership of. For std::unique_ptr and for raw pointers, the out_ptr_t object hands out direct access to the pointer, so that we don't have anything to do (except possibly assign a new deleter) in the ~out_ptr_t destructor. These optimizations avoid requiring additional temporary storage for the pointer (and optional arguments), and avoid additional instructions to copy that pointer into the smart pointer at the end. libstdc++-v3/ChangeLog: PR libstdc++/111667 * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/bits/out_ptr.h: New file. * include/bits/shared_ptr.h (__is_shared_ptr): Move definition to here ... * include/bits/shared_ptr_atomic.h (__is_shared_ptr): ... from here. * include/bits/shared_ptr_base.h (__shared_count): Declare out_ptr_t as a friend. (_Sp_counted_deleter, __shared_ptr): Likewise. * include/bits/unique_ptr.h (unique_ptr, unique_ptr<T[], D>): Declare out_ptr_t and inout_ptr_t as friends. (__is_unique_ptr): Define new variable template. * include/bits/version.def (out_ptr): Define. * include/bits/version.h: Regenerate. * include/std/memory: Include new header. * testsuite/20_util/smartptr.adapt/inout_ptr/1.cc: New test. * testsuite/20_util/smartptr.adapt/inout_ptr/2.cc: New test. * testsuite/20_util/smartptr.adapt/inout_ptr/shared_ptr_neg.cc: New test. * testsuite/20_util/smartptr.adapt/inout_ptr/void_ptr.cc: New test. * testsuite/20_util/smartptr.adapt/out_ptr/1.cc: New test. * testsuite/20_util/smartptr.adapt/out_ptr/2.cc: New test. * testsuite/20_util/smartptr.adapt/out_ptr/shared_ptr_neg.cc: New test. * testsuite/20_util/smartptr.adapt/out_ptr/void_ptr.cc: New test.