Why is std::min failing when windows.h is included?
C++Visual Studio-2005C++ Problem Overview
#include <algorithm>
#include <Windows.h>
int main()
{
int k = std::min(3, 4);
return 0;
}
What is windows doing if I include Windows.h? I can't use std::min
in visual studio 2005. The error message is:
error C2589: '(' : illegal token on right side of '::'
error C2059: syntax error : '::'
C++ Solutions
Solution 1 - C++
The windows.h
header file (or more correctly, windef.h
that it includes in turn) has macros for min
and max
which are interfering.
You should #define NOMINMAX
before including it.
Solution 2 - C++
No need to define anything, just bypass the macro using this syntax:
(std::min)(a, b); // added parentheses around function name
(std::max)(a, b);
Solution 3 - C++
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 includingwindef.h
means these macros won't get defined, and so the compiler can compilestd::min
. - Putting brackets around
std::min
means 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.
Solution 4 - C++
As others mentioned, the errors are due to min/max macros that are defined in windows header(s). There are three ways of disabling them.
-
#define NOMINMAX
before including header, this is generally a bad technique of defining macros in order to affect the following headers; -
define
NOMINMAX
in compiler command line/IDE. The bad part about this decision is that if you want to ship your sources, you need to warn the users to do the same; -
simply undefine the macros in your code before they are used
#undef min #undef max
This is probably the most portable and flexible solution.
Solution 5 - C++
Try something like this:
#define NOMINMAX
#include <windows.h>
By default, windows.h defines min
and max
as macros. When those are expanded, code that tries to use std::min
(for example) will end up looking something like this:
int k = std::(x) < (y) ? (x) : (y);
The error message is telling you that std::(x)
isn't allowed.
Solution 6 - C++
In my case, project did not include windows.h
or windef.h
explicitly. It was using Boost. So, I resolved the issue by going to the project Properties -> C/C++ -> Preprocessor
, and appending NOMINMAX
in the Preprocessor Definitions
(VS 2013, VS 2015).
Solution 7 - C++
For people including windows.h, put the following in effected headers:
#include windows headers ...
pragma push_macro("min")
pragma push_macro("max")
#undef min
#undef max
#include headers expecting std::min/std::max ...
...
pragma pop_macro("min")
pragma pop_macro("max")
In source files just #undef min and max.
#include windows headers ...
#undef min
#undef max
#include headers expecting std::min/std::max ...
Solution 8 - C++
To solve this issue I just create header file named fix_minmax.h
without include guards
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#ifdef MAX
#undef MAX
#endif
#define MAX max
#ifdef MIN
#undef MIN
#endif
#define MIN min
#include <algorithm>
using std::max;
using std::min;
Basic usage is like this.
// Annoying third party header with min/max macros
#include "microsoft-mega-api.h"
#include "fix_minmax.h"
Pros of this approach is that it works with every kind of included file or part of code. This also saves your time when dealing with code or libraries that depend on min
/max
macros
Solution 9 - C++
#define NOMINMAX
is the trick to suppress the macro definitions of max and min
Solution 10 - C++
I'd assume windows.h does define min as a macro, e.g. like
#define min(a,b) ((a < b) ? a : b)
That would explain the error message.