December 21, 2005
Flexible C++ #14: Finding Child Windows with Simulated Local Functions
Compiler Gremlins: Visual C++ Multiple Symbol Definitions in Header Only Form
In the form shown, the C++ implementation compiles and links correctly with all common Win32 compilers, including Borland, Metrowerks CodeWarrior, Comeau, Digital Mars, GCC, Intel, Open Watcom and Visual C++.
To incorporate the function into the STLSoft libraries, which are 100-percent header-only, the function required only the inclusion of an inline specifier. In that form, it continues to work with all the compilers mentioned, with the exception of Visual C++ (all versions from 5.0-8.0 (beta) inclusive), which manages to insert a record of each of the ChildFind methods in each compilation unit; not exactly in the spirit of the language rules!
To make this work for versions 5.0 and 6.0 was a little sneaky, but quite manageable. Experience told me that a template wouldn't exhibit this problem, so I turned it into a template in the following way:
templateFindFirstChildById() is implemented in terms of an instantiation of the template FindFirstChildById_N(), which, for whatever unfathomable reason, causes the correct behaviour from Visual C++. Unfortunately, something seems to have happened on the way to Visual C++ 7, as this only cures the problem for Visual C++ 5.0 and 6.0. The fix required for versions 7.0, 7.1 and 8.0 (beta) is more kill that cure:
struct FindFirstChildById_class
{
class ChildFind
{
. . . // Identical definition to previous version
}
static HWND FindFirstChildById_N(HWND hwndParent, int id)
{
if(::GetDlgCtrlID(hwndParent) == id)
{
return hwndParent;
}
else
{
ChildFind find(hwndParent, id);
return find;
}
}
};
inline HWND FindFirstChildById(HWND hwndParent, int id)
{
return FindFirstChildById_class::FindFirstChildById_N(hwndParent, id);
}
In both cases, we've had to leak type information out of the function, so have somewhat defeated our motivation. If you're writing portable code that must work with Visual C++, the answer is probably to avoid the simulated function technique, and opt for the second of the fix forms. If you're compiler set does not include Visual C++, however, then go for maximum encapsulation with gay abandon.
|
|
||||||||||||||||||||||||||||
|
|
|
|