Costantino Grana
Costantino Grana

Reputation: 3428

The use of T[] as a template parameter

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

Answers (1)

Kerrek SB
Kerrek SB

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

Related Questions