unique and perfect forwarding
Why is there no std::make_unique
function template in the standard C++11 library? I find
std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));
a bit verbose. Wouldn't the following be much nicer?
auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);
This hides the new
nicely and only mentions the type once.
Anyway, here is my attempt at an implementation of make_unique
:
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
It took me quite a while to get the std::forward
stuff to compile, but I'm not sure if it's correct. Is it? What exactly does std::forward<Args>(args)...
mean? What does the compiler make of that?
Herb Sutter, chair of the C++ standardization committee, writes on his blog:
That C++11 doesn't include make_unique
is partly an oversight, and it will almost certainly be added in the future.
He also gives an implementation that is identical with the one given by the OP.
Edit: std::make_unique
now is part of C++14.
Nice, but Stephan T. Lavavej (better known as STL) has a better solution for make_unique
, which works correctly for the array version.
#include <memory>
#include <type_traits>
#include <utility>
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::false_type, Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::true_type, Args&&... args) {
static_assert(std::extent<T>::value == 0,
"make_unique<T[N]>() is forbidden, please use make_unique<T[]>().");
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[sizeof...(Args)]{std::forward<Args>(args)...});
}
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return make_unique_helper<T>(std::is_array<T>(), std::forward<Args>(args)...);
}
This can be seen on his Core C++ 6 video.
An updated version of STL's version of make_unique is now available as N3656. This version got adopted into draft C++14.
While nothing stops you from writing your own helper, I believe that the main reason for providing make_shared<T>
in the library is that it actually creates a different internal type of shared pointer than shared_ptr<T>(new T)
, which is differently allocated, and there's no way to achieve this without the dedicated helper.
Your make_unique
wrapper on the other hand is mere syntactic sugar around a new
expression, so while it might look pleasing to the eye, it doesn't bring anything new
to the table. Correction: this isn't in fact true: Having a function call to wrap the new
expression provides exception safety, for example in the case where you call a function void f(std::unique_ptr<A> &&, std::unique_ptr<B> &&)
. Having two raw new
s that are unsequenced with respect to one another means that if one new expression fails with an exception, the other may leak resources. As for why there's no make_unique
in the standard: It was just forgotten. (This happens occasionally. There's also no global std::cbegin
in the standard even though there should be one.)
Also note that unique_ptr
takes a second template parameter which you should somehow allow for; this is different from shared_ptr
, which uses type erasure to store custom deleters without making them part of the type.
上一篇: 所有权/删除区域设置(std :: locale)
下一篇: 独特和完美的转发