C++ 任何类型资源的自定义STL删除器

C++ 任何类型资源的自定义STL删除器,c++,stl,c++14,C++,Stl,C++14,我查看了许多关于定制清洁剂的链接,但仍然没有找到答案。 对于那些对解决方案感兴趣的人,跳到问题底部的1/2更新。在讨论过程中发现的解决方案1/2,感谢积极和专注的参与者。 我想为某物制作一个自定义的自动删除程序。让我们看看下面的示例 #包括 #pragma注释(lib,“Gdiplus.lib”) .... int HeigthMapFromImg(常量wchar\u t*imgPath,标准::向量和高度) { Gdiplus::GdiplusStartupInput GdiplusStart

我查看了许多关于定制清洁剂的链接,但仍然没有找到答案。
对于那些对解决方案感兴趣的人,跳到问题底部的1/2更新。在讨论过程中发现的解决方案1/2,感谢积极和专注的参与者。 我想为某物制作一个自定义的自动删除程序。让我们看看下面的示例

#包括
#pragma注释(lib,“Gdiplus.lib”)
....
int HeigthMapFromImg(常量wchar\u t*imgPath,标准::向量和高度)
{
Gdiplus::GdiplusStartupInput GdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
int x=来自imgapi的高度映射(imgPath,高度);
Gdiplus::GdiplusShutdown(gdiplusToken);
返回x;
}
注意,这不是一个答案。问题不在于编写自己的包装,也不在于WinAPI。这是一个类似的问题,但答案过于复杂。
在这个示例中,GDI+令牌用于在工作完成时调用GdiplusShutdown。我想用unique\ptr自动化它,我正在尝试类似的方法

int HeigthMapFromImg(常量wchar\u t*imgPath,std::vector&heights)
{
Gdiplus::GdiplusStartupInput GdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL);
std::unique_ptr ptr(gdiplusToken、Gdiplus::gdiplushutdown);
int x=来自imgapi的高度映射(imgPath,高度);
返回x;
}
但不管我怎么做,它都不会编译,代码是用VisualStudio编写的

1>...BitmapReader.cpp(145): message : see reference to class template instantiation 'std::unique_ptr<ULONG_PTR,void (ULONG_PTR)>' being compiled
1>...BitmapReader.cpp(145,109): error C2660: 'std::unique_ptr<ULONG_PTR,void (ULONG_PTR)>::unique_ptr': function does not take 2 arguments
1>...\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\memory(2686,5): message : see declaration of 'std::unique_ptr<ULONG_PTR,void (ULONG_PTR)>::unique_ptr'
1>…BitmapReader.cpp(145):消息:请参阅正在编译的类模板实例化'std::unique_ptr'的参考
1> …BitmapReader.cpp(145109):错误C2660:'std::unique\u ptr::unique\u ptr':函数不接受2个参数
1> …\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\memory(2686,5):消息:请参阅“std::unique\u ptr::unique\u ptr”的声明
STL指针包装器可以很好地处理任何看起来像指针的东西,但是GDI+标记被定义为ULONG_PTR,它被定义为_int64。我希望它是一个PTR,但它不是。当我使用指针时没有问题,例如wchar\u t的缓冲区:

std::wostream&ShowLastError(std::wostream&os)
{
auto localdeleterw=[](wchar_t*a){::LocalFree(a);};
wchar_t*pBuffer=0;
int ret=::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),0,(LPWSTR)和pBuffer,0,0);
如果(!(后退和后退))
{
os评论摘要:


ScopeGuard(正如@IgorTandetnik所建议的)以及@OP可能会问的问题


实际智能指针(由@RemyLebeau建议)

  • (这只适用于指针类型(尽管它可以编译,请参见下面的答案了解详细信息))

来自@OP(即ScopeGuard)的解决方案

模板结构清理器
{
T资源;
~cleaner(){deleter(资源);}
};
///和使用
{
清洁剂c{gdiplusToken};
//在这里做点什么
}

我认为问题在于
std::unique\u ptr
实际上存储了一个指向
ULONG\u ptr
的指针,因此删除器不匹配(看起来应该是
void(ULONG\u ptr*)
)你不能盲目地将
ULONG\u PTR
投射到指针,这根本不安全
std::unique\u PTR
会想将
T*
传递到deleter。但是
GdiplusShutdown
不接受指针类型。你可以在进入
std::unique\u PTR
的过程中将
ULONG\u PTR
投射到某个指针类型,但是
std::unique_ptr
在调用deleter时不会将其抛出。我想,您可以编写自己的deleter,它接受一个指针,将其抛出并将其传递给
gdiplussutdown
。但在这一点上,您最好使用适当的范围保护类,如或@armagedescu。是的,它是这样工作的。我的意思是,您不应该
重新解释演员阵容