make_unique y reenvío perfecto

Resuelto fredoverflow asked hace 13 años • 6 respuestas

¿ Por qué no hay std::make_uniqueuna 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 newmuy 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::forwardmaterial, pero no estoy seguro de si es correcto. ¿Lo es? ¿Qué significa exactamente std::forward<Args>(args)...? ¿Qué opina el compilador de eso?

fredoverflow avatar Aug 12 '11 16:08 fredoverflow
Aceptado

Herb Sutter, presidente del comité de estandarización de C++, escribe en su blog :

Que C++ 11 no lo incluya make_uniquees 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 .

Johan Råde avatar Mar 11 '2012 19:03 Johan Råde

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.

tominator avatar Nov 22 '2012 12:11 tominator

std::make_sharedno 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_ptrdebe asignar un bloque de seguimiento además de mantener el almacenamiento para el puntero real. Sin embargo, debido a que std::make_sharedasigna el objeto real, es posible que std::make_sharedasigne 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 newbloque std::shared_ptrde 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_uniqueharía es ser un poco más conveniente. Nada más que eso.

Nicol Bolas avatar Aug 12 '2011 09:08 Nicol Bolas