Scoped handle (C Plus Plus)
From LiteratePrograms
This is a simple template class making it possible to use the RAII technique on variables without a destructor.
Implementation
<<scoped_handle.hpp>>= #ifndef SCOPED_HANDLE_HPP_INCLUDE_GUARD #define SCOPED_HANDLE_HPP_INCLUDE_GUARD namespace lp { handle_valid scoped_handle } #endif
We use a template with these parameters:
- T - The data type of the handle
- CF - The close function (used by the destructor)
- VF - A function telling if the handle is valid, and optionally invalidating it
<<scoped_handle>>= template<typename T, int (CF)(T), bool (VF)(T, bool)=handle_valid<T> > class scoped_handle { T handle; public: scoped_handle(T handle_): handle(handle_) {}
This destructor uses VF() to check if the handle is valid, and close it with CF() if it is.
<<scoped_handle>>= ~scoped_handle() { if(VF(handle)) CF(handle); }
The handle can be closed manually with this function. We use VF() to invalidate the handle, so that the destructor doesn't try to close it.
<<scoped_handle>>= void close() { if(VF(handle)) CF(handle); VF(handle, true); }
We might want to disassociate the handle from the scoped_handle object. release() provides this functionality.
<<scoped_handle>>= void release() { VF(handle, true); }
We provide operator T(), so that the scoped_handle object can be used as if it was an object of type T.
<<scoped_handle>>= operator T() { return handle; } };
We provide a templated default function for checking/setting validity. This function simply uses 0 as a special value indicating the handle is invalid. This will work for types like FILE * and pointers allocated with malloc(). For other types, like file descriptors/sockets, the user can specialize this template, or specify another function as the third template argument to scoped_handle.
<<handle_valid>>= template<typename T> inline bool handle_valid(T handle, bool invalidate=false) { if(invalidate) handle=0; return (bool)handle; }
Test driver
This example program uses scoped_handle for a FILE * variable. When specifying fclose() as the second template argument, we know the file will be closed when leaving the scope.
<<test.cpp>>= #include"scoped_handle.hpp" #include<stdio.h> #include<iostream> int main() { lp::scoped_handle<FILE*, fclose> file(fopen("test.txt", "w")); if(!(FILE*)file) { std::cerr<<"Could not open file \"test.txt\" for writing\n"; return 1; } fprintf(file, "Hello\n"); return 0; }
Download code |