(no title)
michaelrmmiller | 12 years ago
It also obscures the type of the object. That can be okay if it's only used as a temporary local, but problematic if you ever need to store it as a member or return it from another function. The type signature is verbose and not very descriptive, either. Compare that to:
namespace sdl2 {
using window = std::unique_ptr<SDL_Window, deleter<decltype(SDL_DestroyWindow), SDL_DestroyWindow>>;
}
...
sdl2::window window{SDL_CreateWindow(...)};
If you wanted to do something like what they have, I would create a variant on C++14's std::make_unique. That could look like: template<typename T> struct deleter_traits;
template<> struct deleter_traits<SDL_Window>
{
using custom_deleter = deleter<decltype(SDL_DestroyWindow), SDL_DestroyWindow>;
}
template<typename T, typename... Args> create_unique(Args&&... args)
{
return std::unique_ptr<T, typename deleter_traits<T>::custom_deleter>{new T(std::forward(args))};
}
sdl2::window window = create_unique<SDL_Window>(...);
That looks a lot cleaner to me, at least. And instead of having to write a new function for each type, you just add a new deleter_traits specialization.(I haven't actually compiled any of this so it's probably riddled with syntax errors... hopefully the point still comes across!)
devcodex|12 years ago
That said, I do like this approach and it gives me more to consider when approaching a problem like this again. I'm writing to learn so I welcome the constructive criticism.
michaelrmmiller|12 years ago
Thanks for writing the article! I'm much more in this camp of writing thin resource management rather than full-blown wrappers. And even if I were writing a wrapper, I would use these same techniques you're exploring to manage the resource as a member. It removes the need for any boilerplate whatsoever and in one line expresses all you need to know about the semantics of the object.