Yur*_*kin 1 c++ winapi raii variadic-templates c++11
我正在编写一个模板化的类,它封装了win32处理RAII.这是我到目前为止所得到的:
#define NOMINMAX
#include <Windows.h>
#include <functional>
// problem: optionally pass additional params to the deleter function
template<typename ResourceT, std::function<void(ResourceT)> &Deleter>
class Win32Raii
{
Win32Raii(const Win32Raii &);
Win32Raii &operator=(const Win32Raii &);
public:
Win32Raii()
: m_resource(nullptr)
{}
Win32Raii(const ResourceT &r)
: m_resource(r)
{}
Win32Raii(Win32Raii &&other)
: m_resource(nullptr)
{
*this = std::move(other);
}
~Win32Raii()
{
if (m_resource)
{
Deleter(m_resource);
}
}
Win32Raii &operator=(Win32Raii &&other)
{
std::swap(m_resource, other.m_resource);
return *this;
}
ResourceT get() const { return m_resource; }
private:
ResourceT m_resource;
};
// library code for each resource type
std::function<void(HICON)>destroy_icon = [](HICON h){ ::DestroyIcon(h); };
std::function<void(HDC) > delete_dc = [](HDC h){ ::DeleteDC(h); };
//problem: pass real HWND first arg, not just a nullptr constant
std::function<void(HDC) > release_dc = [](HDC dc) { ::ReleaseDC(nullptr, dc); };
typedef Win32Raii<HICON, destroy_icon> HiconRaii;
typedef Win32Raii<HDC, delete_dc > HdcDelRaii;
typedef Win32Raii<HDC, release_dc > HdcRelRaii;
typedef Win32Raii<HMENU, destroy_menu> HmenuRaii;
//client usage examples
void main()
{
HWND hWnd = ::FindWindowA(nullptr, "some window");
// problem: pass hWnd
HdcRelRaii rdc(::GetDC(hWnd) /*, hWnd */);
HdcDelRaii ddc(::CreateCompatibleDC(rdc.get()));
HiconRaii h;
HiconRaii h2(::LoadIconW(nullptr, IDI_APPLICATION));
h = HiconRaii(std::move(h2));
HiconRaii h3 = std::move(h);
h3 = HiconRaii();
}
Run Code Online (Sandbox Code Playgroud)
对于采用单个HANDLE参数并释放它的API是好的.现在,我的问题是API采用多个参数来释放句柄,比如
ReleaseDC(HWND, HDC);
SelectObject(HDC, HGDIOBJ);
Run Code Online (Sandbox Code Playgroud)
我愿意在删除函数的多个参数的情况下实现的客户端使用语法是:
HdcRelRaii dc_to_release_in_dtor(::GetDC(hWnd), hWnd);
SelectObjRaii obj_to_reselect_in_dtor(::SelectObject(hBrush, hDC), hDC);
Run Code Online (Sandbox Code Playgroud)
所以,最后的问题是:我怎样才能改变
template<typename ResourceT, std::function<void(ResourceT)> &Deleter>
Run Code Online (Sandbox Code Playgroud)
像变种一样的东西
template<
typename ResourceT,
std::function<void(ResourceT, Args&...) &Deleter,
typename... Args>
>
Run Code Online (Sandbox Code Playgroud)
?
显然,非类型参数Deleter依赖于它之后的参数,这是非法的.因此:卡住......
提前致谢
PS欢迎任何有关更好标题,更好用法语法等的想法
这是它的工作原理(使用make_index_sequenceC++ 1y).但是,不确定您使用该参考参数的设计
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;
};
Run Code Online (Sandbox Code Playgroud)
这就是我改变它的方式
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;
};
Run Code Online (Sandbox Code Playgroud)
这与间接层完全兼容
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;
Run Code Online (Sandbox Code Playgroud)
我颠倒了顺序,所以我可以简单地给出多个参数而不包装它们.但那只是品味问题.
| 归档时间: |
|
| 查看次数: |
101 次 |
| 最近记录: |