Perché std :: min non riesce quando è incluso windows.h?


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

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

Cosa fa Windows se includo Windows.h? Non posso utilizzare std::minin Visual Studio 2005. Il messaggio di errore è:

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

Risposte:


157

Il windows.hfile di intestazione (o più correttamente, windef.hche include a sua volta) ha macro per mine maxche interferiscono.

Dovresti #define NOMINMAXprima di includerlo.


28
Uno dei motivi per cui le MACRO sono malvagie. : D
Nawaz

7
Ho usato un progetto / D "NOMINMAX"
Micka

@Micka: dove hai inserito questa opzione nelle impostazioni del tuo progetto? Devo usare la stessa opzione e non so dove mettere ...
flaviu2

@ flaviu2 afair in un campo "comandi aggiuntivi" nella pagina in cui sono riepilogati tutti i comandi di compilazione. Ma al momento non posso controllare
Micka

perché doveva aggiungere: #include <algoritmo> + NOMINMAX
user63898

91

Non è necessario definire nulla, basta bypassare la macro utilizzando questa sintassi:

(std::min)(a, b); // added parentheses around function name
(std::max)(a, b);

1
Grazie, questa è la soluzione che ha funzionato per me. Sto lavorando a un codice in cui non posso semplicemente utilizzare NOMINMAX poiché una parte del codice utilizza il codice di disegno di Windows che necessita delle macro.
Mickaël C. Guimarães

Puoi spiegare perché le parentesi intorno alla magia possono sconfiggere la macro malvagia !? Fantastico
Chen OT

1
Non sono del tutto sicuro di tutta la magia nascosta, ma credo che il parser macro stia cercando di sostituire esattamente "min (", quindi "min) (" viene ignorato dal parser macro. E il nome della funzione viene racchiuso con meanless () non causa problemi al di fuori delle macro.
PolyMesh

1
Bella soluzione, ma non risolve il problema di avere una funzione con il nome mino max(caso d'uso di esempio: implementazione di una classe che si adatta al concetto UniformRandomNumberGenerator ).
Nik Bougalis

Si prega di vedere la risposta di Erik, penso che sia una soluzione migliore. Meno hacky e più chiaro.
PolyMesh

28

Come altri menzionati, gli errori sono dovuti alle macro min / max definite nelle intestazioni di Windows. Ci sono tre modi per disabilitarli.

1) #define NOMINMAXprima di includere l'intestazione, questa è generalmente una cattiva tecnica per definire le macro per influenzare le seguenti intestazioni;

2) definire NOMINMAXnella riga di comando del compilatore / IDE. La parte negativa di questa decisione è che se vuoi spedire i tuoi sorgenti, devi avvertire gli utenti di fare lo stesso;

3) semplicemente annulla la definizione delle macro nel codice prima che vengano utilizzate

#undef min
#undef max

Questa è probabilmente la soluzione più portatile e flessibile.


2
Un altro problema con l'opzione 1 è che semplicemente non funziona sempre. Potrebbero esserci altre intestazioni di Windows incluse altrove che ne hanno effettivamente bisogno, come gdiplus.h. In tal caso l'opzione 3 potrebbe essere la tua unica speranza.
shawn1874

27

Ho ancora problemi occasionalmente con le intestazioni di Windows e la definizione a livello di progetto di NOMINMAX non sembra sempre funzionare. In alternativa all'uso delle parentesi, a volte rendo esplicito il tipo in questo modo:

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

Ciò impedisce anche al preprocessore di corrispondere a mined è probabilmente più leggibile della soluzione alternativa tra parentesi.


3
Sono d'accordo, questa è la soluzione migliore. Stavo solo tornando per dare un'altra risposta quando ho visto che qualcun altro mi ha battuto.
PolyMesh

16

Prova qualcosa di simile:

#define NOMINMAX
#include <windows.h>

Per impostazione predefinita, windows.h definisce mine maxcome macro. Quando vengono espansi, il codice che cerca di utilizzare std::min(ad esempio) finirà per avere un aspetto simile a questo:

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

Il messaggio di errore ti dice che std::(x)non è consentito.


5

Nel mio caso, il progetto non includeva windows.ho windef.hesplicitamente. Stava usando Boost. Quindi, ho risolto il problema andando al progetto Properties -> C/C++ -> Preprocessore aggiungendo NOMINMAXin Preprocessor Definitions(VS 2013, VS 2015).


Per VS 2015 la definizione della macro nel file non ha funzionato per me. La definizione nel progetto ha funzionato.
qqqqq

3

Per le persone che includono windows.h, inserisci quanto segue nelle intestazioni effettuate:

#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")

Nei file sorgente solo #undef min e max.

#include windows headers ...

#undef min
#undef max

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


2

Per risolvere questo problema, creo semplicemente un file di intestazione denominato fix_minmax.h senza protezioni di inclusione

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

L'utilizzo di base è così.

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

I vantaggi di questo approccio è che funziona con ogni tipo di file incluso o parte di codice. Ciò consente inoltre di risparmiare tempo quando si ha a che fare con codice o librerie che dipendono da min/ maxmacro


1

Presumo che windows.h definisca min come macro, ad esempio like

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

Ciò spiegherebbe il messaggio di errore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.