Reputation: 3428
I've recently stumbled upon the use of unique_ptr<T[]>
, where I understand that the aim is to delete the pointer with delete[]
.
What puzzles me is that unique_ptr<T[3]>
is instead invalid (correct me if I'm wrong).
What is the type of T[] in the template? How is it different from T[3]? These are arrays, so shouldn't they be the same? Is there any other use of T[] as a type in templates?
Upvotes: 22
Views: 2017
Reputation: 477464
T[]
is a type. It's the type "array of unknown bound of T
". It is an incomplete type.
T[3]
is also a type. It's the type "array of 3 T
". It is a different type from T[]
, just like int
and double
are different types.
The default_delete
template is specialized partially for incomplete arrays of the form T[]
. However, the complete-array types like T[3]
are forbidden, since that would be very confusing: the unique_ptr
cannot tell how long your array is, since it only handles the array through a pointer to its first element.
(There are technical details in the mechanics: The specialization default_delete<T[3]>
isn't actively prohibited, but since its call operator expects a T(*)[3]
, it will generally not match the pointer that comes from the unique_ptr
, and even if the call were well-formed, a delete
expression on such a pointer is not allowed (= has undefined behaviour). You "cannot delete arrays" if you will, you can only "delete[] arrays via size-erased pointers".)
Note that the make_unique
function template is actively deleted for complete array types.
Curiously, for make_shared
the committee went down a different route and allows complete array types. To do so, shared_ptr<T[N]>
has a precondition that you only construct it from a matching new T[N]
(though that's not checkable in general). (I've never quite understood why that was a good idea.)
Upvotes: 37