Ответ 1
Заголовочный файл windows.h
(вернее, windef.h
, который он включает в свою очередь) имеет макросы для min
и max
, которые мешают.
Вы должны #define NOMINMAX
перед тем, как включить его.
#include <algorithm>
#include <Windows.h>
int main()
{
int k = std::min(3, 4);
return 0;
}
Что делает Windows, если я включаю Windows.h? Я не могу использовать std::min
в Visual Studio 2005. Сообщение об ошибке:
error C2589: '(' : illegal token on right side of '::'
error C2059: syntax error : '::'
Заголовочный файл windows.h
(вернее, windef.h
, который он включает в свою очередь) имеет макросы для min
и max
, которые мешают.
Вы должны #define NOMINMAX
перед тем, как включить его.
Не нужно ничего определять, просто обходите макрос, используя этот синтаксис:
(std::min)(a, b); // added parentheses around function name
(std::max)(a, b);
Как упоминалось выше, ошибки связаны с макросами min/max, которые определены в заголовках (окнах) Windows. Существует три способа их отключения.
1) #define NOMINMAX
перед включением заголовка, это, как правило, плохой метод определения макросов, чтобы влиять на следующие заголовки;
2) определите NOMINMAX
в командной строке /IDE компилятора. Плохая часть этого решения заключается в том, что, если вы хотите отправить свои источники, вам необходимо предупредить пользователей о том, чтобы сделать то же самое;
3) просто отмените определение макросов в коде перед их использованием.
#undef min
#undef max
Это, пожалуй, самое портативное и гибкое решение.
У меня по-прежнему возникают проблемы с заголовками окон, а определение проекта NOMINMAX не всегда работает. В качестве альтернативы использованию круглых скобок я иногда делаю тип явно следующим:
int k = std::min<int>(3, 4);
Это также останавливает препроцессор от соответствия с min
и, возможно, более читабельным, чем обходные скобки.
Попробуйте что-то вроде этого:
#define NOMINMAX
#include <windows.h>
По умолчанию windows.h определяет min
и max
как макросы. Когда они будут расширены, код, который пытается использовать std::min
(например), будет выглядеть примерно так:
int k = std::(x) < (y) ? (x) : (y);
Сообщение об ошибке сообщает, что std::(x)
не разрешено.
В моем случае проект не включал явно windows.h
или windef.h
. Он использовал Boost. Итак, я решил проблему, перейдя в проект Properties -> C/C++ -> Preprocessor
и добавив NOMINMAX
в Preprocessor Definitions
(VS 2013, VS 2015).
#define NOMINMAX
- это трюк для подавления макроопределений max и min
Для людей, включая windows.h, добавьте следующие обработанные заголовки:
#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")
В исходных файлах просто #undef min и max.
#include windows headers ...
#undef min
#undef max
#include headers expecting std::min/std::max ...
Я бы предположил, что window.h определяет min как макрос, например. как
#define min(a,b) ((a < b) ? a : b)
Это объяснит сообщение об ошибке.
Для меня работает следующее.
using namespace std;
int k = min(3, 4);
Чтобы решить эту проблему, я просто создаю заголовочный файл с именем fix_minmax.h
без включения защиты
#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;
Базовое использование выглядит следующим образом.
// Annoying third party header with min/max macros
#include "microsoft-mega-api.h"
#include "fix_minmax.h"
Плюсы этого подхода в том, что он работает с каждым типом включенного файла или части кода. Это также экономит ваше время при работе с кодом или библиотеками, которые зависят от макросов min
/max