[PATCH] Prepare shared_ptr for array support

Jonathan Wakely jwakely@redhat.com
Thu Oct 20 14:41:00 GMT 2016

On 20/10/16 13:08 +0100, Jonathan Wakely wrote:
>This patch doesn't change very much, except for adding
>std::reinterpret_pointer_cast, but it makes it very easy to add array
>support to shared_ptr, as defined for the Library Fundamentals TS by
>https://wg21.link/n3920 and in the process of being added to C++17 by
>The main change is to consistently constrain all template constructors
>and assignment operators. In std::shared_ptr we just forward the
>checks to the std::__shared_ptr base class, so all the hard work is
>done there. The base uses traits that can easily be extended to handle
>array types without touching the uses of those traits (I have that
>patch ready).

Here's the patch to add array support, which is as simple as:

- adding new __shared_count ctor that will result in delete[];
- adjusting the two __sp_xxx traits to handle the array cases;
- moving operator* and operator-> into a new base class, and then
  specializing it so shared_ptr<T[]> has operator[] instead;
- changing element_type to be remove_extent<T>::type instead of T;
- disabling the __has_esft_base detection for array types.

That allows us to remove 650 lines from the experimental::shared_ptr
definition and just inherit directly from __shared_ptr.

Note that the *only* change needed to std::shared_ptr or std::weak_ptr
is to add an extension constructor (see below). My changes to trunk
earlier today mean they are ready to suport arrays now. The code
changes are all to the __shared_ptr and __weak_ptr base classes.

Officially this isn't in the C++17 draft yet, but LWG already approved
P0414R1 and it will be in the straw polls at the end of the Issaquah
meeting next month. I'm not committing it to trunk yet, but I probably
will do before the meeting, as I don't anticipate C++17 being
published without this feature.

The bigger question is whether we want to enable array support
unconditionally, or only for C++17. In C++14 today shared_ptr<int[]>
and shared_ptr<int[N]> are valid ... although they're weird and not
very usable. My preference (as shown in the patch) is to enable it
unconditionally, but add some non-standard member functions for
pre-C++17 to help transition. Specifically operator* and operator->
are defined for shared_ptr<array[]> pre-C++17, and you can do this

  shared_ptr<int> p( unique_ptr<int[]>(new int[1]) );
  p.get()[0] = 1;
  assert( *p == 1 );

This is valid today, and we even have a test checking it works. The
default_delete<int[]> is copied into the shared_ptr and does delete[]
when the refcount drops to zero. C++17 says this is ill-formed. This
patch adds a non-standard constructor that allows this conversion, and
the dereference, for C++11 and C++14 only.

For C++17 the code needs to be changed to:

  shared_ptr<int[]> p( unique_ptr<int[]>(new int[1]) );
  p.get()[0] = 1;
  assert( p[0] == 1 );

-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 34454 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20161020/d8844732/attachment.bin>

More information about the Gcc-patches mailing list