ISO/IEC JTC1/SC22/WG21

N3656 (original) (raw)

Document number: N3656 Date: 2013-04-18 Project: Programming Language C++, Library Working Group Reply-to: Stephan T. Lavavej stl@microsoft.com

make_unique (Revision 1)

I. Introduction

This is a revision of N3588 "make_unique" in response to LWG feedback, containing proposed Standardese and a corresponding implementation.

II. Standardese

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

20.7.1.5 unique_ptr creation [unique.ptr.create]

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

template unique_ptr 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(new typename remove_extent::typen).

template<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(args...) // make_unique<T[]>(n) // make_unique<T[N]>(args...) = delete

#include #include #include #include

namespace std { template struct _Unique_if { typedef unique_ptr _Single_object; };

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

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

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

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

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

}

#include #include using namespace std;

int main() { cout << *make_unique() << endl; cout << *make_unique(1729) << endl; cout << """ << *make_unique() << """ << endl; cout << """ << *make_unique("meow") << """ << endl; cout << """ << *make_unique(6, 'z') << """ << endl;

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

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

cout << endl;

#if defined(ERROR1)
    auto up1 = make_unique<string[]>("error");
#elif defined(ERROR2)
    auto up2 = make_unique<int[]>(10, 20, 30, 40);
#elif defined(ERROR3)
    auto up3 = make_unique<int[5]>();
#elif defined(ERROR4)
    auto up4 = make_unique<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<string[]>("error"); ^ kitty.cpp:61:49: note: candidates are: kitty.cpp:25:9: note: template<class T, class ... Args> typename std::_Unique_if::_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<class T, class ... Args> typename std::_Unique_if::_Single_object std::make_unique(Args&& ...) [with T = std::basic_string []; Args = {}]': kitty.cpp:61:49: required from here kitty.cpp:25:9: error: no type named '_Single_object' in 'struct std::_Unique_if<std::basic_string []>' kitty.cpp:31:9: note: template typename std::_Unique_if::_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<string[]>("error"); ^ kitty.cpp:38:9: note: template<class T, class ... Args> typename std::_Unique_if::_Known_bound std::make_unique(Args&& ...) make_unique(Args&&...) = delete; ^ kitty.cpp:38:9: note: template argument deduction/substitution failed: kitty.cpp: In substitution of 'template<class T, class ... Args> typename std::_Unique_if::_Known_bound std::make_unique(Args&& ...) [with T = std::basic_string []; Args = {}]': kitty.cpp:61:49: required from here kitty.cpp:38:9: error: no type named '_Known_bound' in 'struct std::_Unique_if<std::basic_string []>'

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<int[]>(10, 20, 30, 40); ^ kitty.cpp:63:53: note: candidates are: kitty.cpp:25:9: note: template<class T, class ... Args> typename std::_Unique_if::_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<class T, class ... Args> typename std::_Unique_if::_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<int []>' kitty.cpp:31:9: note: template typename std::_Unique_if::_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<int[]>(10, 20, 30, 40); ^ kitty.cpp:38:9: note: template<class T, class ... Args> typename std::_Unique_if::_Known_bound std::make_unique(Args&& ...) make_unique(Args&&...) = delete; ^ kitty.cpp:38:9: note: template argument deduction/substitution failed: kitty.cpp: In substitution of 'template<class T, class ... Args> typename std::_Unique_if::_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<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::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {}; typename std::_Unique_if::_Known_bound = void]' auto up3 = make_unique<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<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::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {int, int, int, int, int}; typename std::_Unique_if::_Known_bound = void]' auto up4 = make_unique<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<int[5]>(11, 22, 33, 44, 55); ^

(end)