libstdc++: Add C++20 std::make_shared enhancements (P0674R1)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 13 Jan 2022 22:08:43 +0000 (22:08 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 14 Jan 2022 10:14:25 +0000 (10:14 +0000)
commit9a0b518a82db68c5cbd9ea8ccc47c2ff45182519
tree6fce64cd7aacd03b1f14e5cb0282f4d917d49d23
parentfc6f1128ae603164aea6303ce2b3ed0b57e6a378
libstdc++: Add C++20 std::make_shared enhancements (P0674R1)

This adds the overloads of std::make_shared and std::allocate_shared for
creating arrays, added to C++20 by P0674R1.

It also adds std::make_shared_for_overwrite, added to C++20 by P1020R1
(and renamed by P1973R1). The std::make_unique_for_overwite overloads
are already supported.

The original std::make_shared overload is changed to construct a
shared_ptr directly instead of calling std::allocate_shared. This
removes a function call at runtime, and avoids having to do overload
resolution for std::allocate_shared, now that there are five overloads
of it.

Allocating a shared array is done by a new __shared_count constructor.
An array is allocated with space for additional elements at the end and
an instance of new _Sp_counted_array class template is constructed in
that unused capacity.

The non-array form of std::make_shared_for_overwrite uses the same
__shared_count constructor as the original std::make_shared overload,
but a new partial specialization of _Sp_counted_ptr_inplace is selected
when the allocator's value_type is the new _Sp_overwrite_tag type. That
new partial specialization default-initializes its contained object and
destroys it with a destructor call rather than using the allocator.

Despite being C++20 features, this implementation only uses concepts
conditionally, with workarounds when they are not supported. This allows
it to work with older non-GCC compilers (Clang 9 and icc 2021). At some
point we can simplify the code by removing the workarounds.

libstdc++-v3/ChangeLog:

* include/bits/shared_ptr.h (__cpp_lib_shared_ptr_weak_type):
Correct type of macro value.
(shared_ptr): Add additional friend declarations.
(make_shared, allocate_shared): Constrain existing overloads and
remove static_assert.
* include/bits/shared_ptr_base.h (__cpp_lib_smart_ptr_for_overwrite):
New macro.
(_Sp_counted_ptr_inplace<T, Alloc, Lp>): New partial
specialization for use with make_shared_for_overwrite.
(__cpp_lib_shared_ptr_arrays): Update value for C++20.
(_Sp_counted_array_base): New class template.
(_Sp_counted_array): New class template.
(__shared_count(_Tp*&, const _Sp_counted_array_base&, _Init)):
New constructor for allocating shared arrays.
(__shared_ptr(const _Sp_counted_array_base&, _Init)): Likewise.
* include/std/version (__cpp_lib_shared_ptr_weak_type): Correct
type.
(__cpp_lib_shared_ptr_arrays): Update value for C++20.
(__cpp_lib_smart_ptr_for_overwrite): New macro.
* testsuite/20_util/shared_ptr/creation/99006.cc: Adjust
expected errors.
* testsuite/20_util/shared_ptr/creation/array.cc: New test.
* testsuite/20_util/shared_ptr/creation/overwrite.cc: New test.
* testsuite/20_util/shared_ptr/creation/version.cc: New test.
* testsuite/20_util/unique_ptr/creation/for_overwrite.cc: Check
feature test macro. Test non-trivial default-initialization.
libstdc++-v3/include/bits/shared_ptr.h
libstdc++-v3/include/bits/shared_ptr_base.h
libstdc++-v3/include/std/version
libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc
libstdc++-v3/testsuite/20_util/shared_ptr/creation/array.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/shared_ptr/creation/overwrite.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/shared_ptr/creation/version.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/unique_ptr/creation/for_overwrite.cc