<html>
<head>
<TITLE>
ISO/IEC JTC1/SC22/WG21
N3656
</TITLE>
</head>
<body>
<h1>
<img align=top src="/pics/iso44.gif" alt="ISO/">
<img align=top src="/pics/iec44.gif" alt="IEC">
JTC1/SC22/WG21
N3656
</h1>
<pre>
Document number: N3656
Date: 2013-04-18
Project: Programming Language C++, Library Working Group
Reply-to: Stephan T. Lavavej &lt;stl@microsoft.com>


make_unique (Revision 1)


I. Introduction

This is a revision of <a hRef="../2013/n3588.htm">N3588</a> "make_unique" in response to LWG feedback,
containing proposed Standardese and a corresponding implementation.


II. Standardese

* At the end of 20.7.1 [unique.ptr]/6, add:

template&lt;class T, class... Args> unique_ptr&lt;T> make_unique(Args&&... args);
template&lt;class T> unique_ptr&lt;T> make_unique(size_t n);
template&lt;class T, class... Args> unspecified make_unique(Args&&...) = delete;

* Add a new section:

20.7.1.5 unique_ptr creation [unique.ptr.create]

template&lt;class T, class... Args> unique_ptr&lt;T> make_unique(Args&&... args);
Remarks: This function shall not participate in overload resolution unless T is not an array.
Returns: unique_ptr&lt;T>(new T(std::forward&lt;Args>(args)...)).

template&lt;class T> unique_ptr&lt;T> make_unique(size_t n);
Remarks: This function shall not participate in overload resolution unless T is an array of unknown bound.
Returns: unique_ptr&lt;T>(new typename remove_extent&lt;T>::type[n]()).

template&lt;class T, class... Args> unspecified make_unique(Args&&...) = delete;
Remarks: This function shall not participate in overload resolution unless T is an array of known bound.


III. Implementation

C:\Temp>type kitty.cpp
// make_unique&lt;T>(args...)
// make_unique&lt;T[]>(n)
// make_unique&lt;T[N]>(args...) = delete

#include &lt;cstddef>
#include &lt;memory>
#include &lt;type_traits>
#include &lt;utility>

namespace std {
    template&lt;class T> struct _Unique_if {
        typedef unique_ptr&lt;T> _Single_object;
    };

    template&lt;class T> struct _Unique_if&lt;T[]> {
        typedef unique_ptr&lt;T[]> _Unknown_bound;
    };

    template&lt;class T, size_t N> struct _Unique_if&lt;T[N]> {
        typedef void _Known_bound;
    };

    template&lt;class T, class... Args>
        typename _Unique_if&lt;T>::_Single_object
        make_unique(Args&&... args) {
            return unique_ptr&lt;T>(new T(std::forward&lt;Args>(args)...));
        }

    template&lt;class T>
        typename _Unique_if&lt;T>::_Unknown_bound
        make_unique(size_t n) {
            typedef typename remove_extent&lt;T>::type U;
            return unique_ptr&lt;T>(new U[n]());
        }

    template&lt;class T, class... Args>
        typename _Unique_if&lt;T>::_Known_bound
        make_unique(Args&&...) = delete;
}

#include &lt;iostream>
#include &lt;string>
using namespace std;

int main() {
    cout &lt;&lt; *make_unique&lt;int>() &lt;&lt; endl;
    cout &lt;&lt; *make_unique&lt;int>(1729) &lt;&lt; endl;
    cout &lt;&lt; "\"" &lt;&lt; *make_unique&lt;string>() &lt;&lt; "\"" &lt;&lt; endl;
    cout &lt;&lt; "\"" &lt;&lt; *make_unique&lt;string>("meow") &lt;&lt; "\"" &lt;&lt; endl;
    cout &lt;&lt; "\"" &lt;&lt; *make_unique&lt;string>(6, 'z') &lt;&lt; "\"" &lt;&lt; endl;

    auto up = make_unique&lt;int[]>(5);

    for (int i = 0; i &lt; 5; ++i) {
        cout &lt;&lt; up[i] &lt;&lt; " ";
    }

    cout &lt;&lt; endl;

    #if defined(ERROR1)
        auto up1 = make_unique&lt;string[]>("error");
    #elif defined(ERROR2)
        auto up2 = make_unique&lt;int[]>(10, 20, 30, 40);
    #elif defined(ERROR3)
        auto up3 = make_unique&lt;int[5]>();
    #elif defined(ERROR4)
        auto up4 = make_unique&lt;int[5]>(11, 22, 33, 44, 55);
    #endif
}


C:\Temp>g++ -Wall -Wextra kitty.cpp -o kitty.exe && kitty
0
1729
""
"meow"
"zzzzzz"
0 0 0 0 0


C:\Temp>g++ -Wall -Wextra kitty.cpp -o kitty.exe -DERROR1
kitty.cpp: In function 'int main()':
kitty.cpp:61:49: error: no matching function for call to 'make_unique(const char [6])'
         auto up1 = make_unique&lt;string[]>("error");
                                                 ^
kitty.cpp:61:49: note: candidates are:
kitty.cpp:25:9: note: template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Single_object std::make_unique(Args&& ...)
         make_unique(Args&&... args) {
         ^
kitty.cpp:25:9: note:   template argument deduction/substitution failed:
kitty.cpp: In substitution of 'template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Single_object std::make_unique(Args&& ...) [with T = std::basic_string&lt;char> []; Args = {}]':
kitty.cpp:61:49:   required from here
kitty.cpp:25:9: error: no type named '_Single_object' in 'struct std::_Unique_if&lt;std::basic_string&lt;char> []>'
kitty.cpp:31:9: note: template&lt;class T> typename std::_Unique_if&lt;T>::_Unknown_bound std::make_unique(std::size_t)
         make_unique(size_t n) {
         ^
kitty.cpp:31:9: note:   template argument deduction/substitution failed:
kitty.cpp:61:49: note:   cannot convert '"error"' (type 'const char [6]') to type 'std::size_t {aka unsigned int}'
         auto up1 = make_unique&lt;string[]>("error");
                                                 ^
kitty.cpp:38:9: note: template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) &lt;deleted>
         make_unique(Args&&...) = delete;
         ^
kitty.cpp:38:9: note:   template argument deduction/substitution failed:
kitty.cpp: In substitution of 'template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) [with T = std::basic_string&lt;char> []; Args = {}]':
kitty.cpp:61:49:   required from here
kitty.cpp:38:9: error: no type named '_Known_bound' in 'struct std::_Unique_if&lt;std::basic_string&lt;char> []>'


C:\Temp>g++ -Wall -Wextra kitty.cpp -o kitty.exe -DERROR2
kitty.cpp: In function 'int main()':
kitty.cpp:63:53: error: no matching function for call to 'make_unique(int, int, int, int)'
         auto up2 = make_unique&lt;int[]>(10, 20, 30, 40);
                                                     ^
kitty.cpp:63:53: note: candidates are:
kitty.cpp:25:9: note: template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Single_object std::make_unique(Args&& ...)
         make_unique(Args&&... args) {
         ^
kitty.cpp:25:9: note:   template argument deduction/substitution failed:
kitty.cpp: In substitution of 'template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Single_object std::make_unique(Args&& ...) [with T = int []; Args = {}]':
kitty.cpp:63:53:   required from here
kitty.cpp:25:9: error: no type named '_Single_object' in 'struct std::_Unique_if&lt;int []>'
kitty.cpp:31:9: note: template&lt;class T> typename std::_Unique_if&lt;T>::_Unknown_bound std::make_unique(std::size_t)
         make_unique(size_t n) {
         ^
kitty.cpp:31:9: note:   template argument deduction/substitution failed:
kitty.cpp:63:53: note:   candidate expects 1 argument, 4 provided
         auto up2 = make_unique&lt;int[]>(10, 20, 30, 40);
                                                     ^
kitty.cpp:38:9: note: template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) &lt;deleted>
         make_unique(Args&&...) = delete;
         ^
kitty.cpp:38:9: note:   template argument deduction/substitution failed:
kitty.cpp: In substitution of 'template&lt;class T, class ... Args> typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) [with T = int []; Args = {}]':
kitty.cpp:63:53:   required from here
kitty.cpp:38:9: error: no type named '_Known_bound' in 'struct std::_Unique_if&lt;int []>'


C:\Temp>g++ -Wall -Wextra kitty.cpp -o kitty.exe -DERROR3
kitty.cpp: In function 'int main()':
kitty.cpp:65:40: error: use of deleted function 'typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {}; typename std::_Unique_if&lt;T>::_Known_bound = void]'
         auto up3 = make_unique&lt;int[5]>();
                                        ^
kitty.cpp:38:9: error: declared here
         make_unique(Args&&...) = delete;
         ^
kitty.cpp:65:40: error: 'void up3' has incomplete type
         auto up3 = make_unique&lt;int[5]>();
                                        ^


C:\Temp>g++ -Wall -Wextra kitty.cpp -o kitty.exe -DERROR4
kitty.cpp: In function 'int main()':
kitty.cpp:67:58: error: use of deleted function 'typename std::_Unique_if&lt;T>::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {int, int, int, int, int}; typename std::_Unique_if&lt;T>::_Known_bound = void]'
         auto up4 = make_unique&lt;int[5]>(11, 22, 33, 44, 55);
                                                          ^
kitty.cpp:38:9: error: declared here
         make_unique(Args&&...) = delete;
         ^
kitty.cpp:67:58: error: 'void up4' has incomplete type
         auto up4 = make_unique&lt;int[5]>(11, 22, 33, 44, 55);
                                                          ^

(end)
</pre>
</body>
</html>
