740. Please remove *_ptr<T[N]>

Section: 23.11.1 [unique.ptr] Status: CD1 Submitter: Herb Sutter Opened: 2007-10-04 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [unique.ptr].

View all issues with CD1 status.


Please don't provide *_ptr<T[N]>. It doesn't enable any useful bounds-checking (e.g., you could imagine that doing op++ on a shared_ptr<T[N]> yields a shared_ptr<T[N-1]>, but that promising path immediately falters on op-- which can't reliably dereference because we don't know the lower bound). Also, most buffers you'd want to point to don't have a compile-time known size.

To enable any bounds-checking would require run-time information, with the usual triplet: base (lower bound), current offset, and max offset (upper bound). And I can sympathize with the point of view that you wouldn't want to require this on *_ptr itself. But please let's not follow the <T[N]> path, especially not with additional functions to query the bounds etc., because this sets wrong user expectations by embarking on a path that doesn't go all the way to bounds checking as it seems to imply.

If bounds checking is desired, consider a checked_*_ptr instead (e.g., checked_shared_ptr). And make the interfaces otherwise identical so that user code could easily #define/typedef between prepending checked_ on debug builds and not doing so on release builds (for example).

Note that some may object that checked_*_ptr may seem to make the smart pointer more like vector, and we don't want two ways to spell vector. I don't agree, but if that were true that would be another reason to remove *_ptr<T[N]> which equally makes the smart pointer more like std::array. :-)

[ Bellevue: ]

Suggestion that fixed-size array instantiations are going to fail at compile time anyway (if we remove specialization) due to pointer decay, at least that appears to be result from available compilers.

So concerns about about requiring static_assert seem unfounded.

After a little more experimentation with compiler, it appears that fixed size arrays would only work at all if we supply these explicit specialization. So removing them appears less breaking than originally thought.

straw poll unanimous move to Ready.

Proposed resolution:

Change the synopsis under 23.11.1 [unique.ptr] p2:

template<class T> struct default_delete; 
template<class T> struct default_delete<T[]>; 
template<class T, size_t N> struct default_delete<T[N]>;

template<class T, class D = default_delete<T>> class unique_ptr; 
template<class T, class D> class unique_ptr<T[], D>; 
template<class T, class D, size_t N> class unique_ptr<T[N], D>;

Remove the entire section [unique.ptr.dltr.dflt2] default_delete<T[N]>.

Remove the entire section [unique.ptr.compiletime] unique_ptr for array objects with a compile time length and its subsections: [unique.ptr.compiletime.dtor], [unique.ptr.compiletime.observers], [unique.ptr.compiletime.modifiers].