Here's how it could work (using the make_index_sequence
of C++1y). Not sure of your design of using that reference parameter, though
template<typename Signature, std::function<Signature> &Deleter>
class Win32Raii;
template<typename ...Types, std::function<void(Types...)> &Deleter>
class Win32Raii<void(Types...), Deleter> {
public:
~Win32Raii() {
// do as proposed in http://stackoverflow.com/a/7858971/34509
callDelete(std::make_index_sequence<sizeof...(Types)>{});
}
private:
template<std::size_t ...I>
void callDelete(std::integer_sequence<std::size_t, I...>) {
Deleter(std::get<I>(args)...);
}
std::tuple<Types...> args;
};
This is how I would change it
template<typename Deleter, typename ...Params>
class Win32Raii {
public:
Win32Raii(Params... args, Deleter deleter = Deleter());
~Win32Raii() { /* copy most from above ... */ }
private:
Deleter deleter;
std::tuple<Params...> args;
};
This is completely compatible with a layer of indirection
template<typename Type, Type &Deleter>
struct ExoticDeleter {
template<typename ...T>
void operator()(T&&...t) const (
Deleter(std::forward<T>(t)...);
}
};
typedef Win32Raii<
ExoticDeleter<decltype(destroy_icon), destroy_icon>,
HICON
> HiconRaii;
I reversed the order, so that I multiple parameters could be given as simply a sequence without wrapping them. But that's just a matter of taste.