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
NOMINMAX
prior to including windef.h
means these macros won't get defined, and so the compiler can compile std::min
.
- Putting brackets around
std::min
means the preprocessor doesn't see the sequence min(
anymore, and so leaves it alone.
- Putting in the template parameter means that
min<
also is not a match for the macro.