FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
C++
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
December 21, 2005

Flexible C++ #14: Finding Child Windows with Simulated Local Functions

(Page 2 of 3)
Flexible C++ 14

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:

template 
HWND FindFirstChildById_N(HWND hwndParent, int id);

inline HWND FindFirstChildById(HWND hwndParent, int id)
{
	return FindFirstChildById_N<1>(hwndParent, id);
}

template 
HWND FindFirstChildById(HWND hwndParent, int id)
{
  . . . // implementation as shown above
}
FindFirstChildById() 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.

Compiler Gremlins: Visual C++ Multiple Symbol Definitions in Header Only Form.

Back to Article

Previous Page | 1 | 2 | 3 Next Page
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK