2012-07-18 88 views
31

所以我试图从cin获得有效的整数输入,并使用了这个question的答案。如何处理windows.h中max宏与std中的max碰撞?

它建议:

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

这使我在Windows上的错误,说max宏不采取许多争论。这意味着我必须做到这一点

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

为了得到它的工作。这很丑陋;有没有更好的方法来解决这个问题?也许我应该存储max的定义并在之后重新定义它?

+3

您包括?为什么?如果你真的需要它,你可以通过在包含它之前定义** NOMINMAX **来避免定义_min_和_max_宏。 – 2012-07-18 14:50:38

+1

你在使用“namespace std”吗?如果是这样,你故意组合命名空间。 – 2012-07-18 14:51:17

+4

@PaulBeckingham:宏没有命名空间,因此包含windows.h没有任何预防措施将总是与'std :: min' /'std :: max'发生冲突 – PlasmaHH 2012-07-18 15:00:58

回答

64

定义宏NOMINMAX

这将抑制WINDEF.H最小和最大的定义。

8

你只是想刷新cin缓冲区?我一直只是用:

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

这是一个很好的答案,尽管我已经接受了另一个答案,因为它直接回答了问题,而你的问题以另一种方式解决了问题的根源。 :) – Almo 2012-07-18 15:07:25

6

如果你不知道别人有可能包括windows.h没有NOMINMAX,您可以定义一个虚拟的宏可以用来抑制函数宏调用不改变的定义:

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

不是真的既漂亮,但工程和非侵入性。

在使用Windows头文件时,我倾向于尽可能多地将其隐藏,只需将其包含在专门的代码和头文件中(如果需要,使用pimpl),因为它会在全局名称空间中引入太多垃圾。

+2

有趣。只要有可能,我一定会按照建议去除windows.h。 – Almo 2012-07-18 21:53:39

32

括号只是包装的函数名称:

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

没有必要在这种情况下,NOMINMAX宏,再加上你不会得到编译器警告

+0

'std :: max (a,b)'适合我,并且更具可读性。模板参数禁止宏。我错过了什么吗? – 2017-02-03 22:02:30

+0

@DaleWilson是的,你错过了一些东西。你的电话将获得两个值中较大的一个。 std :: numeric_limits :: max()将返回可由size_type存储的最大值。 – Ben 2017-04-25 18:08:20

+1

将parens中的函数名包装成函数指针并调用它,好像通过函数指针实现策略模式一样。这违背了[直接在代码中表达想法]的建议(https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#p1-express-ideas-directly-in-code),因为这种其他语法是而是试图解决min&max宏的定义(而不是通过函数指针实现策略模式)。 Clang/LLVM基础设施建议“'在任何Windows标头之前定义NOMINMAX”#。哪个更好的建议IMO。 – 2017-09-03 16:01:05

1

如果你碰巧使用GDI +,该方法与NOMINMAX不会为你工作,因为GDI +的标题需要全局命名空间中的minmax

而在这种情况下最简单的解决方法是取消定义min/max不再需要它们时。

的代码示例来说明方法:

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

然而,如果名称冲突发生在头文件中,按照此处所述解决,并且您将此头文件包含在需要最小/最大值但尚未定义的地方,那么可能会颠倒这个问题 - 运气不佳... – Aconcagua 2018-01-31 13:11:57