My preferred solution is to make the type explicit like so:
auto k = std::min<int>(3, 4);
This also stops the preprocessor from matching to min and is arguably more readable than the parentheses workaround. One problem with the NOMINMAX solution is when your code gets reused on the next project, you (or someone else) has to start again asking why this 'working' code doesn't compile anymore.
However to answer the actual question why is it failing?
The Windows.h file, includes windef.h which defines the following macros:
#ifndef NOMINMAX
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef min
#define min(a,b) ((a)<(b)?(a):(b))
#endif
#endif
The preprocessor essentially expands macros by looking for the sequence of chars in your code including an open parentheses, in this case min(. It then does a basic search/replace on your code, so after the preprocessor step your code has become:
int k = std::((3)<(4)?(3):(4));
The compiler step, which only has this modified code to go on, is then failing when trying to compile std::( giving you your error message.
You can also now see how the various fixes/workarounds proposed on this page work:
- Defining NOMINMAXprior to includingwindef.hmeans these macros won't get defined, and so the compiler can compilestd::min.
- Putting brackets around std::minmeans the preprocessor doesn't see the sequencemin(anymore, and so leaves it alone.
- Putting in the template parameter means that min<also is not a match for the macro.