Reputation: 819
Writing a wrapper class for a handle that only gets passed by value is relatively easy. I am trying to determine what the best way is to encapsulate handles that need to be passed by address.
For example, writing a wrapper for something like SC_HANDLE that gets passed by value to QueryServiceConfig() is not that difficult. One can either implement a member function like .GetHandle() or implement operator().
The problem (for me at least) is API functions like RegOpenKeyEx() that wants the address of a HKEY.
I've read that overloading operator & is generally a bad idea. What is the recommended way to keep encapsulation (or as much of it as possible) and especially resource collection while allowing API functions access?
Upvotes: 8
Views: 1963
Reputation: 25591
You can always add another layer of indirection to avoid the awful overloading of operator&
and ugly Attach
or Detach
and return a pre-wrapped instance from there.
If you can use C++0x in VS2010 or gcc, or have other ways of accessing std::unique_ptr<>
, then you can do this (error checking omitted for brevity):
struct hkey_deleter
{
void operator()(HKEY hkey)
{
::RegCloseKey(hkey);
}
};
typedef std::unique_ptr<HKEY__, hkey_deleter> regkey;
regkey MyRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired)
{
HKEY hOpenedKey = NULL;
::RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, &hOpenedKey);
return regkey(hOpenedKey);
}
void SomewhereElse()
{
...
regkey r = MyRegOpenKeyEx(HKEY_CLASSES_ROOT, nullptr, 0, KEY_READ);
...
}
The hkey_deleter
will make sure that the registry key gets closed when the scope is exited or regkey::reset()
is called.
Upvotes: 4