37

What problems could I get when defining NOMINMAX before anything else in my program?

As far as I know, this will make <Windows.h> not define the min and max macros such that many conflicts with the STL, e.g. std::min(), std::max(), or std::numeric_limits<T>::min() are resolved.

Am I right in the assumption that only Windows-specific and legacy code will have problems? Almost all libraries should not depend on min() and max() defined as macros?

Edit: Will there be be problems with other Windows headers?

Manuel
  • 6,461
  • 7
  • 40
  • 54
  • 1
    There should not be problems, even with Windows-specific code, but it's possible that there exists some code that wouldn't work. Why don't you try it and see if there are any errors? – Ben Voigt Feb 06 '11 at 14:41
  • For our internal code, `NOMINMAX` works well. However, the library is also used by external developers and I do not want to break their applications. – Manuel Feb 06 '11 at 14:53
  • 1
    `#define` is a compile-time operation. Libraries are linked in, not compiled in. This means they can have their own independent `#define`s. Library users won't see that you `#define`d `NOMINMAX` – MSalters Feb 07 '11 at 10:10
  • 1
    @MSalters: Sorry that I was not clear. I am working on a template library, i.e. any other program using our library has to include our headers (the library itself) which then requires the other program to run with `NOMINMAX`. Still, you are right in that they could put their own code in a different compilation unit. – Manuel Feb 07 '11 at 11:42

4 Answers4

66

Using NOMINMAX is the only not-completely-evil way to include <windows.h>. You should also define UNICODE and STRICT. Although the latter is defined by default by modern implementations.

You can however run into problems with Microsoft’s headers, e.g. for GdiPlus. I’m not aware of problems with headers from any other companies or persons.

If the header defines a namespace, as GdiPlus does, then one fix is to create a wrapper for the relevant header, where you include <algorithm>, and inside the header’s namespace, using namespace std; (or alternatively using std::min; and using std::max):

#define NOMINMAX
#include <algorithm>
namespace Gdiplus
{
  using std::min;
  using std::max;
}

Note that that is very different from a using namespace std; at global scope in header, which one should never do.

I don’t know of any good workaround for the case where there's no namespace, but happily I haven’t run into that, so in practice that particular problem is probably moot.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    @Manuel: yes, apparently. I have to include qualification with weasel word "apparently" because while it works nicely for what I have done, I can't guarantee that there isn't some evil GdiPlus code that I haven't exercised. Somewhere. – Cheers and hth. - Alf Feb 06 '11 at 15:24
  • Another solution is to just _let go_ of the STL's `min`, `max` and let the compiler use Windef.h's `min`, `max` for your GDIPlus projects. Not a big deal. – bobobobo Dec 05 '11 at 16:37
  • 18
    @bobobobo: letting go of `std::min` and `std::max` may not be a big deal for a small personal program, but it means letting go of any header module library that uses them. And that's unacceptable for professional work. It's not a realistic option. – Cheers and hth. - Alf Dec 05 '11 at 22:02
  • 7
    Not only that but there are also useful things like numeric_limits::min and max which are totally different from the min and max macros. – shawn1874 Apr 11 '14 at 20:56
19

I generally use NOMINMAX like this to limit the potential side effects:

#define NOMINMAX
#include <windows.h>
#undef NOMINMAX

That way the scope of the NOMINMAX is relatively confined.

It's not a perfect solution. If something else has already defined NOMINMAX, this pattern fails (though I've never encountered such a case).

If you want to be really, really careful, then you can #include a wrapper header wherever you would have #included windows.h. The wrapper would go something like this:

/* Include this file instead of including <windows.h> directly. */
#ifdef NOMINMAX
#include <windows.h>
#else
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
#endif

You could imagine doing other things in the wrapper, too, like enforcing UNICODE and/or STRICT.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
1

For precompiled header (like stdafx.h) I use this:

#define NOMINMAX
#include <algorithm>
#include <Windows.h>
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#include <gdiplus.h>
#undef min
#undef max
Ajay
  • 18,086
  • 12
  • 59
  • 105
vladon
  • 8,158
  • 2
  • 47
  • 91
-1

I got fix issue by declaring the headers and namespaces in the following order:

#include <windows.h>
#include <minmax.h>
#include <gdiplus.h>

using namespace Gdiplus;
using namespace std;
Anil8753
  • 2,663
  • 4
  • 29
  • 40