|
|
|
Sponsored Link •
|
|
Advertisement
|
I hope I've managed to convince you that Peter was spot on. Overloading
operator &() is just far too much trouble. Consider the
amount of coding time, thinking time and debugging time that is expended
trying to understand and work with libraries that use it, I struggle to
imagine how using it helps the software engineering community[3].
In short, don't do it. In grepping through my source databases at the time of writing, I found eleven uses of it. Of the three that were used in "proper" classes—i.e. those that are not in utility or meta-programming classes—I can probably truly justify only one of them. I removed two immediately[4]. The third I cannot justify, but I'm keeping it for reasons of expediency. For grins, I'll describe this in the following sub-section.
operator &().
The Win32 API defines many non-standard basic structures,
oftentimes for closely related types. Further, since many Win32
compilers did not provide 64-bit integers in the early years of
the operating system, there are several 64-bit structures that
filled in the gap. Two such structures are
ULARGE_INTEGER and FILETIME. Their
structures are as follows:
struct FILETIME
{
uint32_t dwLowDateTime;
uint32_t dwHighDateTime;
};
union ULARGE_INTEGER
{
struct
{
uint32_t LowPart;
uint32_t HighPart;
};
uint64_t QuadPart;
};
Performing arithmetic using the FILETIME structure
is tiresome, to say the least. On little-endian systems, the
layout is identical to that of ULARGE_INTEGER, so
that one can cast instances of one type to the other, hence one
can manipulate two subtract FILETIME structures by
casting them to ULARGE_INTEGER and subtracting the
QuadPart members.
FILETIME ft1 = . . . FILETIME ft2 = . . . FILETIME ft3; GetFileTme(h1, NULL, NULL, &ft1); GetFileTme(h2, NULL, NULL, &ft2); // Subtract them - yuck! reinterpret_cast<ULARGE_INTEGER&>(ft3).QuadPart = reinterpret_cast<ULARGE_INTEGER&>(ft1).QuadPart - reinterpret_cast<ULARGE_INTEGER&>(ft2).QuadPart;
This also is pretty tiresome, so I concocted the
ULargeInteger class. It supplies various arithmetic
operations (see Chapter 29), has a compatible layout with the two
structures, and provides an operator &() overload.
The operator returns an instance of Address_proxy,
whose definition is shown in Listing 26.5:
union ULargeInteger
{
private:
struct Address_proxy
{
Address_proxy(void *p)
: m_p(p)
{}
operator LPFILETIME ()
{
return reinterpret_cast<LPFILETIME>(p);
}
operator LPCFILETIME () const;
operator ULARGE_INTEGER *()
{
return reinterpret_cast<ULARGE_INTEGER*>(p);
}
operator ULARGE_INTEGER const *() const;
private:
void *m_p;
// Not to be implemented
private:
Address_proxy &operator =(Address_proxy const&);
};
Address_proxy operator &()
{
return Address_proxy(this);
}
Address_proxy const operator &() const;
. . .
It holds a reference to the ULargeInteger instance
for which it acts, and it provides implicit conversions to both
FILETIME* and ULARGE_INTEGER*. Since the
proxy class is private, and instances of it are only
returned from the ULargeInteger's address-of
operators, it is relatively proof from abuse, though you'd be
stuck if you tried to put it in an STL container. But it
considerably eases the burden of using these Win32 structures:
ULargeInteger ft1 = . . . ULargeInteger ft2 = . . . GetFileTme(h1, NULL, NULL, &ft1); GetFileTme(h2, NULL, NULL, &ft2); // Subtract them - nice syntax now ULargeInteger ft3 = ft1 - ft2;
BSTR and BStr are far too alike, and have caused
me no end of bother.
Matthew Wilson is author of Imperfect C++, which
is available on Amazon.com at:
http://www.amazon.com/exec/obidos/ASIN/0321228774/
Matthew Wilson is a software development consultant for Synesis Software, and creator of the STLSoft libraries. He is author of Imperfect C++ (Addison-Wesley, 2004), and is currently working on his next two books, one of which is not about C++. Matthew can be contacted via http://imperfectcplusplus.com/. Matthew is co-author with Bjorn Karlsson of The C++ Source column, Smart Pointers.
|
Sponsored Links
|