Warum schlägt std :: min fehl, wenn windows.h enthalten ist?

106
#include <algorithm>
#include <Windows.h>

int main()
{
    int k = std::min(3, 4);
    return 0;
}

Was macht Windows, wenn ich Windows.h einbinde? Ich kann nicht std::minin Visual Studio 2005 verwenden. Die Fehlermeldung lautet:

error C2589: '(' : illegal token on right side of '::'
error C2059: syntax error : '::'
hidayat
quelle

Antworten:

155

Die windows.hHeader-Datei (oder genauer gesagt, windef.hdie sie wiederum enthält) enthält Makros für minund maxdie stören.

Sie sollten es #define NOMINMAXvor dem Einfügen.

paxdiablo
quelle
27
Einer der Gründe, warum MAKROS böse sind. : D
Nawaz
7
Ich habe ein projektweites / D "NOMINMAX" verwendet
Micka
@ Micka: Wo haben Sie diese Option in Ihre Projekteinstellungen eingefügt? Ich muss die gleiche Option verwenden, und ich weiß nicht, wo ich ...
flaviu2
@ flaviu2 afair in einem Feld "Zusätzliche Befehle" auf der Seite, auf der alle Kompilierungsbefehle zusammengefasst sind. Aber kann im Moment nicht überprüfen
Micka
denn es sollte hinzugefügt werden: #include <algorithm> + NOMINMAX
user63898
89

Sie müssen nichts definieren, umgehen Sie einfach das Makro mit dieser Syntax:

(std::min)(a, b); // added parentheses around function name
(std::max)(a, b);
PolyMesh
quelle
1
Vielen Dank, dies ist die Lösung, die für mich funktioniert hat. Ich arbeite an einem Code, bei dem ich NOMINMAX nicht einfach als Teil des Codes verwenden kann. Verwenden Sie Zeichnungscode von Windows, der die Makros benötigt.
Mickaël C. Guimarães
Könntest du erklären, warum Klammern um Magie das böse Makro besiegen können? Cool
Chen OT
1
Ich bin mir nicht ganz sicher, was die Magie unter der Haube angeht, aber ich glaube, der Makro-Parser möchte genau "min (", also "min) (" ersetzen, wird vom Makro-Parser ignoriert. Und der Funktionsname, mit dem umbrochen wird bedeutungslos () verursacht keine Probleme außerhalb von Makros.
PolyMesh
1
Ordentliche Lösung, löst aber nicht das Problem, eine Funktion mit dem Namen minoder zu haben max(Anwendungsbeispiel: Implementierung einer Klasse, die in das UniformRandomNumberGenerator- Konzept passt ).
Nik Bougalis
Bitte sehen Sie Eriks Antwort, ich denke, es ist eine bessere Lösung. Weniger hackig und klarer.
PolyMesh
28

Wie bereits erwähnt, sind die Fehler auf Min / Max-Makros zurückzuführen, die in Windows-Headern definiert sind. Es gibt drei Möglichkeiten, sie zu deaktivieren.

1) #define NOMINMAXVor dem Einfügen von Headern ist dies im Allgemeinen eine schlechte Technik zum Definieren von Makros, um die folgenden Header zu beeinflussen.

2) Definieren Sie NOMINMAXin der Compiler-Befehlszeile / IDE. Das Schlechte an dieser Entscheidung ist, dass Sie die Benutzer warnen müssen, wenn Sie Ihre Quellen versenden möchten.

3) Undefinieren Sie einfach die Makros in Ihrem Code, bevor Sie sie verwenden

#undef min
#undef max

Dies ist wahrscheinlich die tragbarste und flexibelste Lösung.

Gene Bushuyev
quelle
2
Ein weiteres Problem mit Option 1 ist, dass es einfach nicht immer funktioniert. Möglicherweise sind an anderer Stelle andere Windows-Header enthalten, die diese tatsächlich benötigen, z. B. gdiplus.h. In diesem Fall könnte Option 3 Ihre einzige Hoffnung sein.
shawn1874
27

Ich habe immer noch gelegentlich Probleme mit den Windows-Headern und die projektweite Definition von NOMINMAX scheint nicht immer zu funktionieren. Als Alternative zur Verwendung von Klammern mache ich den Typ manchmal so explizit:

int k = std::min<int>(3, 4);

Dies verhindert auch, dass der Präprozessor mit dem Präprozessor übereinstimmt, minund ist wahrscheinlich besser lesbar als die Problemumgehung in Klammern.

Erik
quelle
3
Ich stimme zu, dies ist die beste Lösung. Ich kam gerade zurück, um eine andere Antwort zu geben, als ich sah, dass mich jemand anderes geschlagen hat.
PolyMesh
16

Versuchen Sie so etwas:

#define NOMINMAX
#include <windows.h>

Standardmäßig definiert windows.h minund maxals Makros. Wenn diese erweitert werden, std::minsieht Code, der (zum Beispiel) zu verwenden versucht, ungefähr so ​​aus:

int k = std::(x) < (y) ? (x) : (y);

Die Fehlermeldung sagt Ihnen, dass dies std::(x)nicht erlaubt ist.

Jerry Sarg
quelle
5

In meinem Fall enthielt das Projekt nicht windows.hoder nicht windef.hexplizit. Es wurde Boost verwendet. Also beschloss ich das Problem , indem auf das Projekt gehen Properties -> C/C++ -> Preprocessor, und Anhänge NOMINMAXin dem Preprocessor Definitions(VS 2013 VS 2015).

Terry
quelle
Für VS 2015 hat das Definieren des Makros in der Datei bei mir nicht funktioniert. Das Definieren im Projekt hat funktioniert.
qqqqq
3

Fügen Sie für Personen, einschließlich windows.h, Folgendes in die betroffenen Überschriften ein:

#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 Quelldateien nur #undef min und max.

#include windows headers ...

#undef min
#undef max

#include headers expecting std::min/std::max ...

quelle
1

Ich würde annehmen, dass windows.h min als Makro definiert, z. B. like

#define min(a,b)  ((a < b) ? a : b)

Das würde die Fehlermeldung erklären.

sstn
quelle
1

Um dieses Problem zu lösen , schaffe ich nur Header - Datei namens fix_minmax.h ohne Wachen schließen

#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;

Die grundlegende Verwendung ist wie folgt.

// Annoying third party header with min/max macros
#include "microsoft-mega-api.h"
#include "fix_minmax.h"

Vorteile dieses Ansatzes sind, dass er mit jeder Art von eingeschlossener Datei oder Teil des Codes funktioniert. Dies spart auch Zeit beim Umgang mit Code oder Bibliotheken, die von min/ maxmacros abhängen

In der Reihe
quelle