Sponsored Link •
|
Summary
Attempting to find a compromise between the constraints of a facade that wraps a system API, the limitations of a limited namespace naming scheme, and a user wanting more expressiveness, revealed an interesting compromise in design.
Advertisement
|
A recent post from an STLSoft user expressing dissatisfaction with the STLSoft Windows Registry Library highlighted an interesting conundrum. The user wished to create a registry key in a single statement, something like:
winstl::reg_key key(HKEY_CURRENT_USER, "SOFTWARE\\MyCompany\\MyApp");This uses the
winstl::reg_key
class, which is actually a typedef to a specialisation of
winstl::basic_reg_key
. (Like std::basic_string
, winstl::basic_reg_key
can support different character encodings. Thus, winstl::reg_key
is a typedef of
winstl::basic_reg_key<TCHAR>
. See
here for more details.)
SOFTWARE\MyCompany\MyApp
if it already exists. If it does exist, then an instance of
winstl::registry_exception
is thrown, carrying the result code (ERROR_FILE_NOT_FOUND
)
returned by the underlying Registry API call, RegOpenKeyEx()
.
winstl::basic_reg_key
has three parameters, as follows:
// In namespace winstl template <. . .> class basic_reg_key { . . . public: // Construction basic_reg_key(HKEY keyParent, char_type const* subkeyName, REGSAM accessMask = KEY_ALL_ACCESS); . . . public: // Sub-key operations basic_reg_key create_sub_key(char_type const* subKeyName, REGSAM accessMask = KEY_ALL_ACCESS);
REGSAM
is a Windows API typedef from ACCESS_MASK
, itself a typedef from
DWORD
. KEY_ALL_ACCESS
is defined as follows:
#define KEY_ALL_ACCESS ((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) & (~SYNCHRONIZE))In other words, it's a whole lot of flags covering the bit-width of a
DWORD
. The consequence
of this is that the third constructor parameter, carrying all possible (now and future) values that
may be passed to RegOpenKeyEx()
, cannot also carry an additional flag to enable creation
by constructor, as in:
winstl::reg_key key(HKEY_CURRENT_USER, "SOFTWARE\\MyCompany\\MyApp", KEY_ALL_ACCESS | winstl::reg_key::createKey);The reason is simple. Whatever value we might select for a member constant/enumerator
winstl::reg_key::createKey
cannot be guaranteed not to clash with Windows API constants
to be used with the Windows Registry API functions. (If you're interested, I talk about this issue
at more length in Chapter 17 of my new book,
Extended STL, volume 1: Collections and Iterators, which is
published in three weeks' time. Coincidentally.)
winstl::reg_key key = winstl::reg_key(HKEY_CURRENT_USER, "SOFTWARE").create_sub_key("MyCompany\\MyApp");and instead suggested adding a function to support syntax of the form:
winstl::reg_key key = winstl::create_reg_key(HKEY_CURRENT_USER, "SOFTWARE\\MyCompany\\MyApp");The problem here is that, for good or ill, the use of namespaces within the STLSoft libraries is restricted to a minimum. Specifically, elements from each of the sub-projects (COMSTL for COM components: namespace
comstl
; UNIXSTL for UNIX components: unixstl
; WinSTL for Windows components:
winstl
; and so on) are defined within their single, top-level namespace. (If you're interested,
this is an artefact of the early history of STLSoft, wherein compilers that did not (properly) support
namespaces were supported by the libraries. If there is ever an STLSoft 2.x - we're currently at
1.9.1 -
I might seek to address this and employ library-specific namespaces. But for now it is what it is.)
winstl
namespace to create a key could
not simply be named create()
, or even create_key()
, because that is not
specific to the registry. So, it'd have to be reg_create_key()
or, as the user suggested
create_reg_key()
. This option, with either name, does not appeal to me, as the function will
be ligging around the winstl
namespace with other free functions. But it's not really a
free function, is it? It's actually a non-member function
that is part of the winstl::basic_reg_key
interface.
// In namespace winstl template <. . .> class basic_reg_key { . . . public: // Construction basic_reg_key(HKEY keyParent, char_type const* subkeyName, REGSAM accessMask = KEY_ALL_ACCESS); static basic_reg_key create_key(HKEY keyParent, char_type const* subkeyName, REGSAM accessMask = KEY_ALL_ACCESS); . . . public: // Sub-key operations basic_reg_key create_sub_key(char_type const* subKeyName, REGSAM accessMask = KEY_ALL_ACCESS);This affords the following, relatively expressive, syntax:
winstl::reg_key key = winstl::reg_key::create_key(HKEY_CURRENT_USER, "SOFTWARE\\MyCompany\\MyApp");To be sure, it's not as expressive as the straight (opening, not creating) constructor call. But that's actually a good thing, because it is actually doing something different and significant: creating a key rather than opening it. Positively, it remains closely associated with the STLSoft Windows Registry Library despite there not being a distinct namespace for it.
template <. . .> basic_reg_key<. . .> basic_reg_key<. . .>::create_key(HKEY keyParent, char_type const* subkeyName, REGSAM accessMask) { return basic_reg_key(hkey, NULL, KEY_CREATE_SUB_KEY).create_sub_key(subKeyName, accessMask); }The only noteworthy point is that the
accessMask
is used only for the call to
create_sub_key()
, whereas the constructor permission is KEY_CREATE_SUB_KEY
.
no more, no less.
basic_reg_key
class will be included in STLSoft 1.9.2, to be released in June.
Have an opinion? Readers have already posted 4 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Matthew Wilson adds a new entry to his weblog, subscribe to his RSS feed.
Matthew Wilson is a software development consultant and creator of the FastFormat, Pantheios and STLSoft libraries. He is author of the books Imperfect C++ (Addison-Wesley, October 2004) and Extended STL, volume 1 (Addison-Wesley, 2007), and is currently working on his third, Breaking Up The Monolith: Advanced C++ Design Without Compromise. He has published over 60 articles on C++ and other topics, and has served as columnist and contributing editor for C/C++ Users Journal. Matthew believes that code should be discoverable and largely self-documenting, and lives up to that by being a hopeless documentor. He can be contacted via http://www.imperfectcplusplus.com/ or stlsoft@gmail.com. |
Sponsored Links
|