A traits class for (compound) pointers - beyond what std::pointer_traits offers This is a percolation of ideas which originated this SO question:

Compound pointer traits class with method generalizing make_shared and make_unique?

The std::pointer_traits class offers the following traits, basically:

Types: pointer, element_type, difference_type, and rebind (given a pointer-like type for pointing to T, get a pointer-like type for pointing to U)

Static methods:


to_address - get the plain vanilla T* from some fancy pointer-to-T-like class, if possible
pointer_to - opposite of to_address. This is a fishy method, since it's not clear what it means with respect to resource ownership.


I think it's useful to add at least two methods - for creating a pointer to a new object / array of objects, a-la std::make_shared and std::make_unique, and one for releasing ownership + getting the raw address. Here's my implementation:

#pragma once
#ifndef EXTRA_POINTER_TRAITS_HPP_
#define EXTRA_POINTER_TRAITS_HPP_

#include &lt;memory&gt;

template &lt;typename Ptr&gt;
struct extra_pointer_traits;

template &lt;typename T&gt;
struct extra_pointer_traits&lt;T*&gt;
{
    using ptr_type = T*;
    using element_type = T;

    static ptr_type make(size_t count) { return new T[count]; }
    static ptr_type make()             { return new T;        }
};

template &lt;typename T&gt;
struct extra_pointer_traits&lt;T[]&gt;
{
    using ptr_type = T[];
    using element_type = T;

    static T* make(size_t count) { return new T[count]; }
    static T* make()             { return new T;        }
};

template &lt;typename T, class Deleter&gt;
struct extra_pointer_traits&lt;std::unique_ptr&lt;T[], Deleter&gt;&gt;
{
    using ptr_type = std::unique_ptr&lt;T[], Deleter&gt;;
    using element_type = T;

    static T* release(ptr_type&amp; ptr) { return ptr.release(); }
    static std::unique_ptr&lt;T[], Deleter&gt; make(size_t count)
    {
        return std::make_unique&lt;T[]&gt;(count);
    }
};


template &lt;typename T, class Deleter&gt;
struct extra_pointer_traits&lt;std::unique_ptr&lt;T, Deleter&gt;&gt;
{
    using ptr_type = std::unique_ptr&lt;T, Deleter&gt;;
    using element_type = T;

    static T* release(ptr_type&amp; ptr) { return ptr.release(); }
    static std::unique_ptr&lt;T, Deleter&gt; make()
    {
        return std::make_unique&lt;T&gt;();
    }
};


template &lt;typename T&gt;
struct extra_pointer_traits&lt;std::shared_ptr&lt;T&gt;&gt;
{
    using ptr_type = std::shared_ptr&lt;T&gt;;
    using element_type = typename std::pointer_traits&lt;ptr_type&gt;::element_type;

    // No release()
    static std::shared_ptr&lt;element_type[]&gt; make(size_t count)
    {
        return std::make_shared&lt;element_type[]&gt;(count);
    }
    static std::shared_ptr&lt;element_type&gt; make()
    {
        return std::make_shared&lt;element_type&gt;();
    }
};

#endif // EXTRA_POINTER_TRAITS_HPP_


I'm considering suggesting something like this as an addition to the existing traits class the standards committe, but for now I've implemented it as a separate class.

Note: To clarify - these are not all possible template specializations for pointer-like classes in the standard library, there would be a few more.
First, size_t should be std::size_t everywhere.

Why don't the raw pointer/array cases have release()? Granted, it won't really change any ownership in reality, but it could conceptually.

static ptr_type make(size_t count) { return new T[count]; }
static ptr_type make()             { return new T;        }


I'm not sure this interface is a good idea as is. This only supports Ts with default constructors. What about constructor arguments:

template &lt;typename... Args&gt;
static ptr_type make(Args&amp;&amp;... args)
{
    return new T{std::forward&lt;Args&gt;(args)...};
}


But of course, if you do that, it conflicts with the make(std::size_t) overload. So you'd need a different name for that, like make_n() or something, maybe with an interface like:

template &lt;typename... Args&gt;
static ptr_type make_n(std::size_t count, Args&amp;&amp;... args)
{
    return new T[count]{std::forward&lt;Args&gt;(args)...};
}


However, what about the difference between T{...} and T(...)? Now you need overloads for those cases, too.

Now, as for the overall idea, I'm not a committee member, but I can tell you with absolute certainty that this will never be accepted.

First, what actual problem in use is this supposed to solve? What is an actual use case where this is necessary and offers a significant improvement? I can't think of any situation where this will be useful. Certainly not one that's generalizable, which is mandatory for a standard library addition.

Generally speaking, memory management should be handled by containers, and containers use allocators, and this has no allocator support whatsoever.

Even worse, it hides the allocation method from client code... which is disastrous because you need to know how something was allocated to know how to DEallocate it. As it is, your interface offers a "handy" way to allocate memory, but no way to free it, and in fact goes out of its way to make code less safe by stripping ownership from smart pointers with the release() function.

In summary, I see no general gain from this, and plenty of dangerous drawbacks.