views:

80

answers:

3

I am migrating from Visual Studio 6 to Visual Studio 2008 and I have a function of a component I am using named SetDefaultPrinter.

Unfortunately there is a windows library function now, SetDefaultPrinter, with the same name. And the macro associated with it is getting in the way of me using my function.

This is my workaround I have to call my function:

#undef SetDefaultPrinter
    pNova->SetDefaultPrinter();
#ifdef UNICODE
#define SetDefaultPrinter  SetDefaultPrinterW
#else
#define SetDefaultPrinter  SetDefaultPrinterA
#endif // !UNICODE

Is there a less ugly way around this? And no, I do not have control over that external component to change the name of the function.

+1  A: 

You could use a wrapper around the external component. This is sometimes called the "Adapter" pattern.

// header file
class NovaWrapper
{
  Nova *_nova;
  public:
    void setDefaultPrinter();
};

// implementation file - this file does not include windows.h - you need to make sure it
// does not have visibility of the "bad" SetDefaultPrinter macro
void NovaWrapper::setDefaultPrinter()
{
  _nova->SetDefaultPrinter();
}

Now, modify your client code to use NovaWrapper instead of the underlying instance.

1800 INFORMATION
+3  A: 

This is why C++ added namespaces; too bad the Windows definitions can't use them.

In another source module, where you do NOT include windows.h or any other Windows include files, generate a stub function to call your clashing function.

void MySetDefaultPrinter(CNova * pNova)
{
    pNova->SetDefaultPrinter();
}
Mark Ransom
Unfortunately, Microsoft managed to make namespaces useless here, since almost the entire Win32 API has been turned into macros. SetDefaultPrinter is a macro (mapping to either SetDefaultPrinterA orSetDefaultPrinterW), and as such, the name does not respect namespace scope.In an API full of bad design and WTF moment, this has to be one of the biggest. And unfortunately, it seems like we're stuck with it.
jalf
@jalf - totally agreed. I think it stems from a requirement to keep the Windows API totally C compatible, but the compromises involved are really unfortunate. The headers should have had two sections, one for C++ and one for C.
Mark Ransom
A: 

This was, in the end, fixed by simply swapping the order of includes. Apparently, the developers of this component realized the problem before me, so they included SetDefaultPrinterA and SetDefaultPrinterW in the component that are just aliases for SetDefaultPrinter. So that if windows.h renames the function, it's not a problem.

Nick Whaley