make_unique y reenvío perfecto
¿ Por qué no hay std::make_unique
una plantilla de funciones en la biblioteca estándar de C++ 11? Encuentro
std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));
un poco detallado. ¿No sería mucho mejor lo siguiente?
auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);
Esto oculta new
muy bien el tipo y solo lo menciona una vez.
De todos modos, aquí está mi intento de implementación de 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)...));
}
Me tomó bastante tiempo compilar el std::forward
material, pero no estoy seguro de si es correcto. ¿Lo es? ¿Qué significa exactamente std::forward<Args>(args)...
? ¿Qué opina el compilador de eso?
Herb Sutter, presidente del comité de estandarización de C++, escribe en su blog :
Que C++ 11 no lo incluya
make_unique
es en parte un descuido, y es casi seguro que se agregará en el futuro.
También ofrece una implementación idéntica a la dada por el OP.
Editar: std::make_unique
ahora es parte de C++14 .
Bien, pero Stephan T. Lavavej (más conocido como STL) tiene una mejor solución para make_unique
, que funciona correctamente para la versión de matriz.
#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)...);
}
Esto se puede ver en su video Core C++ 6 .
Una versión actualizada de la versión STL de make_unique ahora está disponible como N3656 . Esta versión fue adoptada en el borrador C++14.
std::make_shared
no es solo una abreviatura de std::shared_ptr<Type> ptr(new Type(...));
. Hace algo que no puedes hacer sin él.
Para realizar su trabajo, std::shared_ptr
debe asignar un bloque de seguimiento además de mantener el almacenamiento para el puntero real. Sin embargo, debido a que std::make_shared
asigna el objeto real, es posible que std::make_shared
asigne tanto el objeto como el bloque de seguimiento en el mismo bloque de memoria.
Entonces, si bien std::shared_ptr<Type> ptr = new Type(...);
habría dos asignaciones de memoria (una para el new
bloque std::shared_ptr
de seguimiento), std::make_shared<Type>(...)
se asignaría un bloque de memoria.
Esto es importante para muchos usuarios potenciales de std::shared_ptr
. Lo único que std::make_unique
haría es ser un poco más conveniente. Nada más que eso.