78

So I was trying to get valid integer input from cin, and used an answer to this question.

It recommended:

#include <Windows.h> // includes WinDef.h which defines min() max()
#include <iostream>
using std::cin;
using std::cout;

void Foo()
{
    int delay = 0;
    do
    {
        if(cin.fail())
        {
            cin.clear();
            cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
        cout << "Enter number of seconds between submissions: ";
    } while(!(cin >> delay) || delay == 0);
}

Which gives me an error on Windows, saying that the max macro doesn't take that many arguments. Which means I have to do this

do
{
    if(cin.fail())
    {
        cin.clear();
#undef max
        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    cout << "Enter number of seconds between submissions: ";
} while(!(cin >> delay) || delay == 0);

To get it to work. That's pretty ugly; is there a better way to work around this issue? Maybe I should be storing the definition of max and redefining it afterward?

Community
  • 1
  • 1
Almo
  • 15,187
  • 13
  • 66
  • 91
  • 7
    Do You include ? Why? If You really need it you can avoid define of _min_ and _max_ macros by defining **NOMINMAX** before including it. – Piotr Tkaczyk Jul 18 '12 at 14:50
  • 1
    Are you using "namespace std"? If so, you are deliberately combining namespaces. – Paul Beckingham Jul 18 '12 at 14:51
  • 8
    @PaulBeckingham: macros have no namespaces, and thus including windows.h without any precautions will always collide with `std::min`/`std::max` – PlasmaHH Jul 18 '12 at 15:00
  • 1
    possible duplicate of [Strange C++ errors with code that has min()/max() calls](http://stackoverflow.com/questions/14165/strange-c-errors-with-code-that-has-min-max-calls) – PlasmaHH Jul 18 '12 at 15:03
  • check http://stackoverflow.com/questions/1394132/macro-and-member-function-conflict – Mr. Ree Dec 27 '14 at 08:39

5 Answers5

118

Define the macro NOMINMAX:

This will suppress the min and max definitions in Windef.h.

hmjd
  • 117,013
  • 19
  • 199
  • 247
  • 6
    For some reason the url does not work for me, even though it is returned as only hit for: https://support.microsoft.com/en-us/search?query=NOMINMAX – malat Nov 20 '19 at 14:47
86

Just wrap the function name in parenthesis:

(std::numeric_limits<size_type>::max)()

No need for the NOMINMAX macro in this case, plus you won't get compiler warnings

NIRO
  • 869
  • 6
  • 2
  • 2
    `std::max(a,b)` works for me and is more readable. The template parameter suppresses the macro. Am I missing something? – Dale Wilson Feb 03 '17 at 22:02
  • 4
    @DaleWilson Yes, you're missing something. Your call will get the larger of two values. std::numeric_limits::max() will return the maximum value that can be stored by size_type. – Ben Apr 25 '17 at 18:08
  • 2
    Wrapping the function name in parens is taking the function pointer & invoking it as though implementing a strategy pattern via function pointers. That defies the advice of [expressing ideas directly in code](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p1-express-ideas-directly-in-code) since this other syntax is rather an attempt to work around the definition of the min & max macros (not an implementation of strategy pattern via function pointer). The Clang/LLVM infrastructure suggests "`#define NOMINMAX` before any Windows header". Which is better advice IMO. – Louis Langholtz Sep 03 '17 at 16:01
  • 2
    @LouisLangholtz With VS projects there is common stdafx.h and when you place NOMINMAX in it, there can be errors in other files, which use the macros. – ggurov Jul 30 '18 at 12:37
  • 1
    When working with a project that includes legacy code (which might use the old max and min macros), this is your best option. The ugly syntax is a trade-off. – jakar Dec 07 '18 at 16:52
  • 1
    FTR, I believe `std::numeric_limits::max ()` (with an extra space) also works. But I'd recommend just defining `NOMINMAX`. – celticminstrel Aug 23 '19 at 19:04
  • 1
    Genius-level solution. This is the best answer in contexts that involve other libraries etc... – atlex2 Sep 15 '21 at 15:39
12

If you don't know whether somebody else might have included windows.h without NOMINMAX, you might define a dummy macro which can be used to suppress function-like macro invocations without changing the definition:

#define DUMMY
...
std::numeric_limits<std::streamsize>::max DUMMY ()

Not really pretty either, but works and is non-intrusive.

When working with the Windows header file, I prefer to hide it as much as I can by including it only in specialized code and header files (using pimpl if necessary), because it throws just too much garbage into the global namespace.

Philipp
  • 45,923
  • 12
  • 81
  • 107
  • 3
    Interesting. I will definitely be following advice to peel out windows.h wherever possible. – Almo Jul 18 '12 at 21:53
  • This is an excellent way to do things when writing a header for use by others and you cannot control whether the user #includes windows.h before your header – Phil Rosenberg Jan 12 '21 at 13:31
10

Are you just trying to flush the cin buffer? I always just used:

cin.ignore(cin.rdbuf()->in_avail());
Littlegator
  • 375
  • 3
  • 17
  • This is a good answer, though I have accepted the other one as it directly answers the question, while yours addresses the source of the problem in another way. :) – Almo Jul 18 '12 at 15:07
6

If you happen to use GDI+, the approach with NOMINMAX won't work for you, because headers of GDI+ require min or max in global namespace.

And the simplest workaround in this case is to undefine min/max when they are no longer needed.

The code sample to illustrate the approach:

//#define NOMINMAX - this won't work
#include <Windows.h>
#include <gdiplus.h>
#undef max
#undef min
...
#include <cxxopts.hpp>
Aconcagua
  • 22,474
  • 4
  • 33
  • 56
AntonK
  • 1,081
  • 1
  • 12
  • 21
  • Potentially reverses the problem, though: if name clash happens in a header, solved as described here, and you include the this header somewhere requiring min/max yet to be defined - bad luck... – Aconcagua Jan 31 '18 at 13:11