I read the book of Richter, then Myers, there were questions about RAII, and more precisely, the classes of wrappers for the automatic release of resources. To begin with, Richter uses NULL in his examples, while Myers says in black and white that this is not worth doing, and in general: nullptr is not the same as NULL . According to Richter:

typedef VOID (WINAPI* PFNENSURECLEANUP)(UINT_PTR); template<class TYPE, PFNENSURECLEANUP pfn, UINT_PTR tInvalid = NULL> class CEnsureCleanup { public: CEnsureCleanup() { m_t = tInvalid; } CEnsureCleanup(TYPE t) : m_t((UINT_PTR) t) { } ~CEnsureCleanup() { Cleanup(); } BOOL IsValid() { return(m_t != tInvalid); } BOOL IsInvalid() { return(!IsValid()); } TYPE operator=(TYPE t) { Cleanup(); m_t = (UINT_PTR) t; return(*this); } operator TYPE() { return (TYPE) m_t; } void Cleanup() { if (IsValid()) { pfn(m_t); m_t = tInvalid; } } private: UINT_PTR m_t; }; #define MakeCleanupClass(className, tData, pfnCleanup) \ typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup> className; #define MakeCleanupClassX(className, tData, pfnCleanup, tInvalid) \ typedef CEnsureCleanup<tData, (PFNENSURECLEANUP) pfnCleanup, \ (INT_PTR) tInvalid> className; MakeCleanupClass(CEnsureCloseHandle, HANDLE, CloseHandle); MakeCleanupClassX(CEnsureCloseFile, HANDLE, CloseHandle, INVALID_HANDLE_VALUE); MakeCleanupClass(CEnsureLocalFree, HLOCAL, LocalFree); MakeCleanupClass(CEnsureGlobalFree, HGLOBAL, GlobalFree); MakeCleanupClass(CEnsureRegCloseKey, HKEY, RegCloseKey); MakeCleanupClass(CEnsureCloseServiceHandle, SC_HANDLE, CloseServiceHandle); MakeCleanupClass(CEnsureCloseWindowStation, HWINSTA, CloseWindowStation); MakeCleanupClass(CEnsureCloseDesktop, HDESK, CloseDesktop); MakeCleanupClass(CEnsureUnmapViewOfFile, PVOID, UnmapViewOfFile); MakeCleanupClass(CEnsureFreeLibrary, HMODULE, FreeLibrary); 

But, in my opinion, this is anti-pattern. First, all the same NULL , and secondly, the problem of the copy constructor. Does a generalization make sense in principle and, if so, how to implement it correctly? If it is easy, explain with examples, as I start to get confused.

  • The problem here is probably not in NULL, the use of which is quite normal, if WinAPI requires it, but in the use of windows types in the public interface. There is no copy constructor here, and there is no moving one. Also present are c-style casting, an implicit one-parameter constructor, the absence of exception specifiers, meaningless macros, and all sorts of other problems. Richter can be safely sent to the trash (in any case, this example). - VTT

0