Let's break it down:
If this weren't library code you mightn't care about proper forwarding (which isn't important anyway since the function you're calling is written in C and C doesn't have lvalue-references!! - unnecessary complexity), so you would sloppily write this as:
template<typename Creator, typename Destructor, typename... Arguments>
auto make_resource(Creator c, Destructor d, Arguments&&... args)
{
typedef decltype(*c(args...)) ResourceType;
return std::unique_ptr<ResourceType, void(*)(ResourceType*)>(c(args...), d);
}
Which is much easier to understand, yes? Your standard passing multiple arguments along thing like you'd normally do when writing a custom printf.Actually, now that I've had time to think about it, you can simpify the original code:
template<typename Creator, typename Destructor, typename... Arguments>
auto make_resource(Creator c, Destructor d, Arguments&&... args)
{
auto r = c(std::forward<Arguments>(args...));
typedef typename std::decay<decltype(*r)>::type ResourceType;
return std::unique_ptr<ResourceType, void(*)(ResourceType*)>(r, d);
}
And again, written sloppily: template<typename Creator, typename Destructor, typename... Arguments>
auto make_resource(Creator c, Destructor d, Arguments&&... args)
{
auto r = c(args...);
typedef decltype(*r) ResourceType;
return std::unique_ptr<ResourceType, void(*)(ResourceType*)>(r, d);
}
Or, if you don't mind repetition of ResourceType: template<typename Creator, typename Destructor, typename... Arguments>
auto make_resource(Creator c, Destructor d, Arguments&&... args)
{
auto r = c(args...);
return std::unique_ptr<decltype(*r), void(*)(decltype(r))>(r, d);
}
Clearer?An alternative way to get the value type is to use std::remove_pointer_t:
using ResourceType = std::remove_pointer_t<decltype(c(args...))>;Your simplification of the original code is great! I like how pulling out the creation of the the resource to its own line makes the typedef and unique_ptr initialization much easier to read (as far as templates go that is, a real sticking point here today).
I have updated my article and attributed the clarification to you, thanks again for your feedback and comments!
Another use on here suggested a shorter and more efficient way to write the code [0].
http://onlinehut.org/2013/01/smart-pointers-are-not-just-for...
though I was trying to use that method to manage handles, not pointers. I eventually had to write a wrapper for handles for it to fulfill the requirements imposed by unique_ptr.
With your experience, how would you write a general solution for this problem?
You end up exposing the SDL functionality as a normal class object, and everything's much more straightforward.