4

Under Windows, after the line

#include <windows.h>

many symbols become defined in the global namespace. For example, Polygon gets defined. Is there then any convenient way to use this symbol to define a custom class as in the following?

class Polygon {
    ...
};

Does putting class Polygon in its own namespace imply that it has to be explicitly qualified with that namespace every time it is used? In other words, is there any way to hide or mask particular definitions from windows.h? Or is there any other practical workaround?

I thought of:

#define Polygon Polygon_windows
#include <windows.h>
#undef Polygon

but this seems quite ugly.

And of course one cannot use namespace windows { #include <windows.h> }.

Hugues
  • 2,865
  • 1
  • 27
  • 39
  • 3
    Does `#define WIN32_LEAN_AND_MEAN` before `#include ` get rid of it? There are about 50 more of those, but `WIN32_LEAN_AND_MEAN` is the bucket-get-rid-of-a-bunch-of-stuff macro – David Feb 13 '13 at 03:51
  • You're many years late to this party I'm afraid. Windows.h defines a lot of stupid crap (like `min` and `max`, seriously!). As Dave said, they provide ways to disable many of the declarations. – Ed S. Feb 13 '13 at 04:48
  • 1
    The fundamental problem here is the design of the C language. A pre-processor and #include does not make a modularization system. Of course, C was designed in a different era so we can forgive the lack of vision. But can't we move on by now? – David Heffernan Feb 13 '13 at 08:53
  • @Dave Thanks for the suggestion. Unfortunately, `WIN32_LEAN_AND_MEAN` did not help. Neither did the more aggressive `VC_EXTRALEAN`. But I found that `#define NOGDI` does omit the symbol (if one does not need GDI). – Hugues Feb 14 '13 at 23:00

2 Answers2

3

The only real defense against such a macro is to isolate definition and direct usage of the class-with-colliding-name down in an implementation file.

Note that <windows.h> is one of the absolute worst regarding willy-nilly macro definitions, with thousands upon thousands of them…

Just yesterday I noted yet another such conflict, between <windows.h>, or to more precise between <windowsx.h>, and Microsoft's own code. Namely the SelectFont macro colliding with the CMFCButton::SelectFont method. Disclaimer: I haven't tried it out, but it does seem like Microsoft in this case didn't even avoid a name collision with their own code.

And then there's the infamous use of min and max macros in <gdiplus.h>. Or, there was such usage. I haven't checked lately.

So, take care! :-)

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I recommend this thread for how to do this: http://stackoverflow.com/questions/2574549/forward-declare-hinstance-and-friends I recommending forward declarations with `struct` instead of class but otherwise this is fine. This has saved me so much hassle I cannot upvote this answer enough. – NtscCobalt Feb 13 '13 at 05:17
  • @NtlsCobalt: instead of a brittle forward-declaration of `HINSTANCE` (its definition has changed over the years, and may depend on whether `STRICT` is defined), just use an unsigned integer in the publicly visible definition, – Cheers and hth. - Alf Feb 13 '13 at 05:29
  • `DECLARE_HANDLE` makes a typedef pointer to a named structure type or void pointer. If you modified the declaration for a STRICT version you should be fine on that count as well but I've never tested it. The added benefit of using the method in the link is that you can later actually include the real definition and then HINSTANCE objects don't require any casts as they will match the real definition. – NtscCobalt Feb 13 '13 at 05:57
  • 2
    The problem illustrated by `SelectFont` is quite common. It comes up when you don't include `` in the header that defines a class, but you do include `` in the source file that defines its member functions. Of course, if you drink the Microsoft kool-aid and use their precompiled headers everywhere the problem doesn't come up. Sigh. – Pete Becker Feb 13 '13 at 13:52
-2

Use namespaces, that's what they're for!

namespace YourNamespace{
  class Polygon{ 
    //
  };
}

Another work-around would be to do this:

#include <windows.h>
#define Polygon _Polygon

class _Polygon{ 
};
Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • 2
    Macros don't respect namespaces. – Cheers and hth. - Alf Feb 13 '13 at 05:00
  • Yes my first suggestion is namespace. Then macro – Aniket Inge Feb 13 '13 at 05:01
  • it seems like you don't understand. a namespace does not help regarding the macro name collision, *because* macros don't respect namespaces. just try it before posting (you can do that retroactively). – Cheers and hth. - Alf Feb 13 '13 at 05:02
  • @Cheersandhth.-Alf I think I get it now. Why not undef the macro? – Aniket Inge Feb 13 '13 at 05:04
  • Undefining is a last resort. Because for a Windows macro, other code may rely on the macro being there. Which you might discover at a much later time when you try to use some library, say. – Cheers and hth. - Alf Feb 13 '13 at 05:06
  • @Cheers and hth. - Alf, Macro definitions are per source file, so unless someone elses header actually #includes windows.h or requires windows.h to be included before its inclusion this won't be an issue. If they are doing that then you are going to have to write a PIMPL wrapper. – NtscCobalt Feb 13 '13 at 05:21
  • 1
    @NtscCobalt: i'm sorry, your comment appears to be meaningless techno-babble. macro definitions are not "per source file", and it's difficult to understand what that could mean. the OP's problem is a clash with a Windows API macro name, not including `` is therefore not an option. and a pimpl wrapper is not necessarily required. again, sorry, but everything in your comment was wrong or meaningless. – Cheers and hth. - Alf Feb 13 '13 at 05:26
  • @Cheersandhth.-Alf My apologies: macros that are defined outside of the preprocessor definitions only exist in the scope of whatever follows them (limited to a compilation unit). Generally I assume you are not including windows.h or any library specific headers into your own headers. If you must `#include ` but you absolutely cannot have macro undefines you will need to use the PIMPL pattern which allows the implementation to be hidden away in a separate file and thus not subject anyone who includes your header to also end up getting hideous macros. – NtscCobalt Feb 13 '13 at 05:43
  • Polygon is not actually a macro. Those hacks were only needed to deal with functions that take a string, Unicode vs Ansi. Polygon doesn't. So this workaround is perfectly good. – Hans Passant Dec 05 '15 at 11:41