c++ - ¿Cómo uso un eliminador personalizado con un miembro std:: unique_ptr?
c++11 move-semantics (4)
Asumiendo que create
y destroy
son funciones gratuitas (lo que parece ser el caso del fragmento de código del PO) con las siguientes firmas:
Bar* create();
void destroy(Bar*);
Puedes escribir tu clase Foo
así
class Foo {
std::unique_ptr<Bar, void(*)(Bar*)> ptr_;
// ...
public:
Foo() : ptr_(create(), destroy) { /* ... */ }
// ...
};
Tenga en cuenta que no necesita escribir ningún lambda o eliminador personalizado aquí porque destroy
ya es un eliminador.
Tengo una clase con un miembro unique_ptr.
class Foo {
private:
std::unique_ptr<Bar> bar;
...
};
La barra es una clase de terceros que tiene una función create () y una función destroy ().
Si quisiera usar un std::unique_ptr
con él en una función independiente, podría hacerlo:
void foo() {
std::unique_ptr<Bar, void(*)(Bar*)> bar(create(), [](Bar* b){ destroy(b); });
...
}
¿Hay alguna manera de hacer esto con std::unique_ptr
como miembro de una clase?
Es posible hacer esto limpiamente usando un lambda en C ++ 11 (probado en G ++ 4.8.2).
Dado este typedef
reutilizable:
template<typename T>
using deleted_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
Puedes escribir:
deleted_unique_ptr<Foo> foo(new Foo(), [](Foo* f) { customdeleter(f); });
Por ejemplo, con un FILE*
:
deleted_unique_ptr<FILE> file(
fopen("file.txt", "r"),
[](FILE* f) { fclose(f); });
Con esto obtienes los beneficios de la limpieza segura de excepciones usando RAII, sin necesidad de probar / atrapar ruido.
Simplemente puede usar std::bind
con una función de destrucción.
std::unique_ptr<Bar, std::function<void(Bar*)>> bar(create(), std::bind(&destroy,
std::placeholders::_1));
Pero por supuesto también puedes usar una lambda.
std::unique_ptr<Bar, std::function<void(Bar*)>> ptr(create(), [](Bar* b){ destroy(b);});
Solo necesitas crear una clase de eliminador:
struct BarDeleter {
void operator()(Bar* b) { destroy(b); }
};
y proporcionarlo como el argumento de la plantilla de unique_ptr
. Aún tendrá que inicializar unique_ptr en sus constructores:
class Foo {
public:
Foo() : bar(create()), ... { ... }
private:
std::unique_ptr<Bar, BarDeleter> bar;
...
};
Hasta donde yo sé, todas las bibliotecas c ++ populares implementan esto correctamente; ya que BarDeleter
realidad no tiene ningún estado, no necesita ocupar ningún espacio en el unique_ptr
.