web-dev-qa-db-fra.com

Problèmes possibles avec NOMINMAX sur Visual C++

Quels problèmes puis-je rencontrer en définissant NOMINMAX avant toute autre chose dans mon programme?

Autant que je sache, ceci fera en sorte que <Windows.h> ne définisse pas les macros min et max telles que de nombreux conflits avec le STL, par exemple. std::min(), std::max() ou std::numeric_limits<T>::min() sont résolus.

Ai-je raison de supposer que seuls les codes hérités de Windows et spécifiques auront des problèmes? Presque toutes les bibliothèques ne devraient pas dépendre de min() et max() définis en tant que macros.

Edit: Y aura-t-il des problèmes avec d'autres en-têtes Windows?

32
Manuel

Utiliser NOMINMAX est le seul moyen non-totalement-pervers d’inclure <windows.h>. Vous devez également définir UNICODE et STRICT. Bien que ce dernier soit défini par défaut par les implémentations modernes.

Vous pouvez toutefois rencontrer des problèmes avec les en-têtes de Microsoft, par exemple pour GdiPlus. Je ne suis pas au courant de problèmes avec des en-têtes d'autres sociétés ou personnes.

Si l’en-tête définit un espace de noms, à l’instar de GdiPlus, l’un des correctifs consiste à créer un emballage pour l’en-tête approprié, dans lequel vous incluez <algorithm>, et dans l’espace de nom de cet en-tête, using namespace std; (ou alternativement using std::min; et using std::max):

#define NOMINMAX
#include <algorithm>
namespace Gdiplus
{
  using std::min;
  using std::max;
}

Notez que c'est très différent d'un using namespace std; à portée globale dans l'en-tête, que l'on devrait ne jamais faire .

Je ne connais aucune solution de contournement valable pour le cas où il n’existe pas d’espace de noms, mais heureusement, je n’ai pas eu à le faire, alors dans la pratique, ce problème particulier est probablement sans objet.

49

J'utilise généralement NOMINMAX comme ceci pour limiter les effets secondaires potentiels:

#define NOMINMAX
#include <windows.h>
#undef NOMINMAX

De cette façon, la portée de la variable NOMINMAX est relativement limitée.

Ce n'est pas une solution parfaite. Si quelque chose a déjà défini NOMINMAX, ce modèle échoue (même si je n'ai jamais rencontré un tel cas).

Si vous voulez être vraiment très prudent, vous pouvez alors inclure # un en-tête de wrapper partout où vous avez # inclus Windows.h. Le wrapper irait quelque chose comme ça:

/* Include this file instead of including <windows.h> directly. */
#ifdef NOMINMAX
#include <windows.h>
#else
#define NOMINMAX
#include <windows.h>
#undef NOMINMAX
#endif

Vous pouvez également imaginer faire d'autres choses dans l'emballage, comme appliquer UNICODE et/ou STRICT.

13
Adrian McCarthy

J'ai résolu le problème en déclarant les en-têtes et les espaces de noms dans l'ordre suivant:

#include <windows.h>
#include <minmax.h>
#include <gdiplus.h>

using namespace Gdiplus;
using namespace std;
0
Anil8753

Pour les en-têtes précompilés (comme stdafx.h), j'utilise ceci:

#define NOMINMAX
#include <algorithm>
#include <Windows.h>
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#include <gdiplus.h>
#undef min
#undef max
0
vladon