2012-07-18 10 views
31

Así que estaba tratando de obtener una entrada entera válida de cin, y usé una respuesta a este question.¿Cómo trato con la macro máxima en windows.h que colisiona con max in std?

Se recomienda:

#include <Windows.h> // includes WinDef.h which defines min() max() 
#include <iostream> 
using std::cin; 
using std::cout; 

void Foo() 
{ 
    int delay = 0; 
    do 
    { 
     if(cin.fail()) 
     { 
      cin.clear(); 
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
     } 
     cout << "Enter number of seconds between submissions: "; 
    } while(!(cin >> delay) || delay == 0); 
} 

Lo que me da un error en Windows, diciendo que el max macro no toma que muchos argumentos. Lo que significa que tengo que hacer esto

do 
{ 
    if(cin.fail()) 
    { 
     cin.clear(); 
#undef max 
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
    } 
    cout << "Enter number of seconds between submissions: "; 
} while(!(cin >> delay) || delay == 0); 

Para que funcione. Eso es bastante feo; ¿Hay una mejor manera de solucionar este problema? Tal vez debería almacenar la definición de max y redefinirla después?

+3

¿Se incluye ? ¿Por qué? Si realmente lo necesita, puede evitar definir macros _min_ y _max_ definiendo ** NOMINMAX ** antes de incluirlo. –

+1

¿Está utilizando "namespace std"? Si es así, estás combinando deliberadamente espacios de nombres. –

+4

@PaulBeckingham: las macros no tienen espacios de nombres y, por lo tanto, incluir windows.h sin ninguna precaución siempre colisionará con 'std :: min' /' std :: max' – PlasmaHH

Respuesta

64

Definir el macro NOMINMAX:

Esto suprimirá el min y definiciones Max en Windef.h.

8

¿Estás tratando de eliminar el buffer de cin? Siempre acabo de utilizar:

cin.ignore(cin.rdbuf()->in_avail()); 
+0

Esta es una buena respuesta, aunque he aceptado la otra ya que responde directamente la pregunta, mientras que la suya aborda el origen del problema de otra manera. :) – Almo

6

Si no sé si alguien más podría haber incluido windows.h sin NOMINMAX, es posible definir una macro ficticio que se puede utilizar para suprimir las invocaciones de macros tipo función sin cambiar la definición:

#define DUMMY 
... 
std::numeric_limits<std::streamsize>::max DUMMY() 

No es realmente bonito tampoco, pero funciona y no es intrusivo.

Cuando trabajo con el archivo de encabezado de Windows, prefiero ocultarlo tanto como puedo incluyéndolo solo en código especializado y archivos de encabezado (usando pimpl si es necesario), porque arroja demasiada basura al espacio de nombres global .

+2

Interesante. Definitivamente seguiré consejos para pelar windows.h siempre que sea posible. – Almo

32

Simplemente envuelva el nombre de función en paréntesis:

(std::numeric_limits<size_type>::max)() 

No hay necesidad de la macro NOMINMAX en este caso, además de que no recibirá advertencias del compilador

+0

'std :: max (a, b)' funciona para mí y es más legible. El parámetro de plantilla suprime la macro. ¿Me estoy perdiendo de algo? –

+0

@DaleWilson Sí, te estás perdiendo algo. Su llamada obtendrá el mayor de dos valores. std :: numeric_limits :: max() devolverá el valor máximo que se puede almacenar mediante size_type. – Ben

+1

Envolver el nombre de la función en parens es tomar el puntero de la función e invocarlo como si se implementara un patrón de estrategia a través de punteros de función. Eso desafía el consejo de [expresar ideas directamente en el código] (https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p1-express-ideas-directly-in-code) ya que esta otra sintaxis es más bien un intento de evitar la definición de las macros mín y máx (no una implementación del patrón de estrategia a través del puntero de función). La infraestructura Clang/LLVM sugiere "' #define NOMINMAX' antes de cualquier encabezado de Windows ". Cuál es mejor consejo IMO. –

1

Si quieres pasar a utilizar GDI +, el enfoque con NOMINMAX no funcionará para usted, porque los encabezados de GDI + requieren min o max en el espacio de nombres global.

Y la solución más simple en este caso es undefinir min/max cuando ya no sean necesarios.

El código de ejemplo para ilustrar el enfoque:

//#define NOMINMAX - this won't work 
#include <Windows.h> 
#include <gdiplus.h> 
#undef max 
#undef min 
... 
#include <cxxopts.hpp> 
+0

Posiblemente revierte el problema: si el choque de nombres ocurre en un encabezado, se resuelve como se describe aquí, e incluye este encabezado en algún lugar que requiera min/max aún por definir - mala suerte ... – Aconcagua

Cuestiones relacionadas