JTC1/SC22/WG21
N3656
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
* At the end of 20.7.1 [unique.ptr]/6, add:
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
template<class T> unique_ptr<T> make_unique(size_t n);
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
* Add a new section:
20.7.1.5 unique_ptr creation [unique.ptr.create]
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
Remarks: This function shall not participate in overload resolution unless T is not an array.
Returns: unique_ptr<T>(new T(std::forward<Args>(args)...)).
template<class T> unique_ptr<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<T>(new typename remove_extent<T>::type[n]()).
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<T>(args...)
// make_unique<T[]>(n)
// make_unique<T[N]>(args...) = delete
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
namespace std {
template<class T> struct _Unique_if {
typedef unique_ptr<T> _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 <iostream>
#include <string>
using namespace std;
int main() {
cout << *make_unique<int>() << endl;
cout << *make_unique<int>(1729) << endl;
cout << "\"" << *make_unique<string>() << "\"" << endl;
cout << "\"" << *make_unique<string>("meow") << "\"" << endl;
cout << "\"" << *make_unique<string>(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<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<class T, class ... Args> typename std::_Unique_if<T>::_Single_object std::make_unique(Args&& ...) [with T = std::basic_string<char> []; 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<char> []>'
kitty.cpp:31:9: note: template<class T> typename std::_Unique_if<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<string[]>("error");
^
kitty.cpp:38:9: note: template<class T, class ... Args> typename std::_Unique_if<T>::_Known_bound std::make_unique(Args&& ...) <deleted>
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<T>::_Known_bound std::make_unique(Args&& ...) [with T = std::basic_string<char> []; 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<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<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<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<class T, class ... Args> typename std::_Unique_if<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<int []>'
kitty.cpp:31:9: note: template<class T> typename std::_Unique_if<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<int[]>(10, 20, 30, 40);
^
kitty.cpp:38:9: note: template<class T, class ... Args> typename std::_Unique_if<T>::_Known_bound std::make_unique(Args&& ...) <deleted>
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<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<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<T>::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {}; typename std::_Unique_if<T>::_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<T>::_Known_bound std::make_unique(Args&& ...) [with T = int [5]; Args = {int, int, int, int, int}; typename std::_Unique_if<T>::_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)