该类主要方便写单行的利用RAII思想进行析构的对象,
两种功能(1)通过Func(xxx)形式释放(2)通过obj->Func(xxx)形式释放
使用了比较猥琐的__if_exist语法
#include <assert.h>
#include <windows.h>
#pragma warning(disable:4996)
namespace XYZ
{
class __CsRaiiRss_global_dummy_class
{
public:
//定义一个变量用来判断一个模板能否是__CsRaiiRss_global_dummy_class参数
BOOL __CsRaiiRss_global_dummy_class__test_exist_member_201907011318__abc__this_variable_is_too_speciall_so_ithink_other_class_doesntHasIt__mmm;
};
template<typename T, typename FREE_FUN_TYPE, typename IN_CLASS_TYPE = __CsRaiiRss_global_dummy_class, DWORD_PTR defVal = 0>
class CSimpleRAIIResource
{
public:
T* m_p;
CSimpleRAIIResource(T* from, FREE_FUN_TYPE fnFree, IN_CLASS_TYPE* thiz = 0)
{
if (!fnFree)
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr");
}
m_p = from;
m_fnFree = fnFree;
m_thiz = thiz;
}
~CSimpleRAIIResource() {
self_destroy();
}
operator T*() const {
return m_p;
}
bool operator !() {
return (m_p == defVal);
}
CSimpleRAIIResource& operator = (T* p)
{
if (!(m_p == p))
{
self_destroy();
m_p = p;
}
return *this;
}
private:
void self_destroy()
{
if (m_p)
{
if (m_fnFree)
{
if (m_thiz)
{
__if_not_exists(IN_CLASS_TYPE::__CsRaiiRss_global_dummy_class__test_exist_member_201907011318__abc__this_variable_is_too_speciall_so_ithink_other_class_doesntHasIt__mmm)
{
((*m_thiz).*m_fnFree)(m_p);
}
}
else
{
__if_exists(IN_CLASS_TYPE::__CsRaiiRss_global_dummy_class__test_exist_member_201907011318__abc__this_variable_is_too_speciall_so_ithink_other_class_doesntHasIt__mmm)
{
m_fnFree(m_p);
}
}
}
else
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr, m_p will leak");
}
m_p = NULL;
}
}
FREE_FUN_TYPE m_fnFree;
IN_CLASS_TYPE* m_thiz;
};
};
class MyClass
{
public:
void Test()
{
}
HANDLE GetFile()
{
return CreateFileW(L"C:\\aa.txt", GENERIC_WRITE | GENERIC_READ, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
}
void ReleaseFile(HANDLE h)
{
CloseHandle(h);
}
};
int main()
{
std::cout << "Hello World!\n";
MyClass myClass;
{
XYZ::CSimpleRAIIResource<void, void(MyClass::*)(HANDLE), MyClass, (DWORD_PTR)INVALID_HANDLE_VALUE> spFile
(
myClass.GetFile(),
&MyClass::ReleaseFile,
&myClass
);
if (spFile)
{
DWORD dwWrite = 0;
WriteFile(spFile, L"HelloWorld", 20, &dwWrite, 0);
}
}
{
XYZ::CSimpleRAIIResource<FILE, int(*)(FILE*)> spFile(_wfopen(L"C:\\bb.txt", L"wb+"), fclose);
if (spFile)
{
fwrite(L"HelloWorlK", 2, 10, spFile);
}
spFile = _wfopen(L"C:\\cc.txt", L"wb+");
if (spFile)
{
fwrite(L"HelloWorlN", 2, 10, spFile);
}
}
}
若不用if——exist,则目前C++不支持同名类模板的参数重载,那么只能实现两个不同名字的类模板
namespace EFG
{
template <typename T, typename TBASE>
class __CSimpleRAIIResource__base_xxx
{
public:
T* m_p;
__CSimpleRAIIResource__base_xxx(T* from)
{
m_p = from;
}
~__CSimpleRAIIResource__base_xxx()
{
self_destroy();
}
operator T*() const {
return m_p;
}
bool operator !() {
return (m_p == defVal);
}
TBASE& operator = (T* p)
{
if (!(m_p == p))
{
self_destroy();
m_p = p;
}
return *this;
}
private:
void self_destroy()
{
if (m_p)
{
((TBASE*)this)->Do_Free();
m_p = NULL;
}
}
};
template<typename T, typename FREE_FUN_TYPE, typename IN_CLASS_TYPE, DWORD_PTR defVal = 0>
class CSimpleRAIIResource : public __CSimpleRAIIResource__base_xxx<T, CSimpleRAIIResource<T, FREE_FUN_TYPE, IN_CLASS_TYPE, defVal> >
{
public:
CSimpleRAIIResource(T* from, FREE_FUN_TYPE fnFree, IN_CLASS_TYPE* thiz) :m_p(from)
{
if (!fnFree)
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr");
}
m_fnFree = fnFree;
m_thiz = thiz;
}
CSimpleRAIIResource(T* from, FREE_FUN_TYPE fnFree) :m_p(from)
{
if (!fnFree)
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr");
}
m_fnFree = fnFree;
m_thiz = 0;
}
void Do_Free()
{
if (m_fnFree)
{
//最难的就是这里,统一个指针的不同语法式
if (m_thiz)
{
((*m_thiz).*m_fnFree)(m_p);
}
else
{
assert(0 && "code error m_thiz=null !");
}
}
else
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr, m_p will leak");
}
}
private:
FREE_FUN_TYPE m_fnFree;
IN_CLASS_TYPE* m_thiz;
};
template<typename T, typename FREE_FUN_TYPE, DWORD_PTR defVal = 0>
class CSimpleRAIIResourceFromGlobal : public __CSimpleRAIIResource__base_xxx<T, CSimpleRAIIResourceFromGlobal<T, FREE_FUN_TYPE, defVal> >
{
public:
CSimpleRAIIResourceFromGlobal(T* from, FREE_FUN_TYPE fnFree) :m_p(from)
{
if (!fnFree)
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr");
}
m_fnFree = fnFree;
}
void Do_Free()
{
if (m_fnFree)
{
m_fnFree(m_p);
}
else
{
assert(0 && "Invalid Useage of CSimpleRAIIResource, fnFree cannot = nullptr, m_p will leak");
}
}
private:
FREE_FUN_TYPE m_fnFree;
};
};