c++ - Typedef a shared_ptr type with a static custom deleter, similar to unique_ptr -
i have read through many questions on over custom deleter shared_ptr
, unique_ptr
, , difference between two. but, still haven't found clear answer question:
how can 1 best go creating type acts shared_ptr
custom deleter, similar how unique_ptr
has deleter part of type definition?
for unique_ptr
usage, use deleter class, handles deletion of individual types (limiting 2 types, brevity):
struct sdl_deleter { void operator()( sdl_surface* ptr ) { if (ptr) sdl_freesurface( ptr );} void operator()( sdl_rwops* ptr ) { if (ptr) sdl_rwclose( ptr );} }; using surfaceptr = std::unique_ptr<sdl_surface, sdl_deleter>; using rwopsptr = std::unique_ptr<sdl_rwops, sdl_deleter>;
which can used like
surfaceptr surface(img_load("image.png"));
and call sdl_freesurface
upon destruction.
this fine , well. however, how 1 go achieving same shared_ptr
? type defined as
template< class t > class shared_ptr;
and way provide custom deleter through constructor. doesn't feel right user of shared_ptr
wrapper needs know pointer type wrapped, , how pointer supposed deleted. best way achieve same kind of usage unique_ptr
example of above.
in other words, end with:
surfaceshptr surface(img_load("image.png"));
instead of of like
surfaceshptr surface(img_load("image.png"), [=](sdl_surface* ptr){sdl_freesurface(ptr);});
or, better
surfaceshptr surface(img_load("image.png"), sdl_deleter());
is there way this, without having create raii wrapper class (instead of typedef), adding more overhead?
if answer "this isn't possible". why not?
the other answer provided here close asked done through function returns of unique_ptr
custom deleter, can implicitly converted shared_ptr
.
the answer given deleter defined type trait not possible std::shared_ptr
. answer suggested alternative, use function returns unique_ptr
, implicitly converted shared_ptr
.
since isn't part of type, possible make simple mistake, leading memory leaks. wanted avoid.
for example:
// correct usage: shared_ptr<sdl_surface> s(createsurface(img_load("image.png"))); // memory leak: shared_ptr<sdl_surface> s(img_load("image.png"));
the concept want express having deleter part of type (which unique_ptr
allows), functionality of shared_ptr
. suggested solution deriving shared_ptr
, , providing deleter type template argument. takes no additional memory, , works in same way unique_ptr
.
template<class t, class d = std::default_delete<t>> struct shared_ptr_with_deleter : public std::shared_ptr<t> { explicit shared_ptr_with_deleter(t* t = nullptr) : std::shared_ptr<t>(t, d()) {} // reset function, needs set deleter. void reset(t* t = nullptr) { std::shared_ptr<t>::reset(t, d()); } };
together deleter class (thanks jonathan wakely. way cleaner macro (now removed)):
struct sdl_deleter { void operator()(sdl_surface* p) const { if (p) sdl_freesurface(p); } void operator()(sdl_rwops* p) const { if (p) sdl_rwclose(p); } }; using surfaceptr = std::unique_ptr<sdl_surface, sdl_deleter>; using surfaceshptr = shared_ptr_with_deleter<sdl_surface, sdl_deleter>; using rwopsptr = std::unique_ptr<sdl_rwops, sdl_deleter>; using rwopsshptr = shared_ptr_with_deleter<sdl_rwops, sdl_deleter>;
instances surfaceshptr
members type guaranteed clean properly, same surfaceptr
, wanted.
// correct usage (much harder use incorrectly now): surfaceshptr s(img_load("image.png")); // still correct usage s.reset(img_load("other.png"));
i'll leave while, comments, etc, without accepting answer. maybe there more dangerous caveats i've missed (having non-virtual destructor not being one, parent shared_ptr
given charge of deletion).
Comments
Post a Comment