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?
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With