You can manage all kinds of other resources, for example GDI objects. In my last project I have this:
Code:
template <class Handle>
class GdiSelect;
template <class Handle>
class GdiHandle: boost::noncopyable
{
Handle h;
bool selected;
public:
GdiHandle(Handle h): h(h), selected(false) {}
~GdiHandle()
{
assert(!selected);
DeleteObject(h);
}
friend class GdiSelect<Handle>;
};
template <class Handle>
class GdiSelect: boost::noncopyable
{
GdiHandle<Handle>* new_handle;
Handle old_handle;
HDC hdc;
public:
GdiSelect(GdiHandle<Handle>& gdi_handle, HDC dc):
new_handle(&gdi_handle),
old_handle(NULL),
hdc(dc)
{
if (new_handle->h) {
old_handle = static_cast<Handle>(SelectObject(dc, new_handle->h));
new_handle->selected = true;
}
}
~GdiSelect()
{
if (old_handle) {
SelectObject(hdc, old_handle);
new_handle->selected = false;
}
}
};
GdiHandle automatically deletes the managed object if it goes out of scope. GdiSelect selects the resource into device context and restores the old selection as it goes out of scope. Usage is like this:
Code:
...
GdiHandle<HFONT> header_font(create_header_font(hdc));
while (printing_pages) {
...
//draw header.
//GdiSelect restores the previous font in destructor, hence another scope
{
GdiSelect<HFONT> select_header_font(header_font, hdc);
if (!DrawText(hdc, filename.c_str(), filename.size(), &header, DT_LEFT) ||
!DrawText(hdc, page_number.c_str(), page_number.size(), &header, DT_RIGHT)) {
//failed printing header. Do nothing?
}
}
...
}
It also takes another approach to the rule of three: make the class non-copyable and non-assignable (declare the copy constructor/operator= private or inherit from such a class).