เหตุใด std :: min จึงล้มเหลวเมื่อรวม windows.h


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

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

windows กำลังทำอะไรถ้าฉันรวม Windows.h? ฉันไม่สามารถใช้std::minใน Visual Studio 2005 ข้อความแสดงข้อผิดพลาดคือ:

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

คำตอบ:


160

windows.hไฟล์ส่วนหัว (หรือมากกว่าอย่างถูกต้องwindef.hว่ามันรวมถึงในทางกลับกัน) มีแมโครสำหรับminและmaxที่มีการรบกวน

คุณควร#define NOMINMAXรวมไว้ก่อน


29
สาเหตุหนึ่งที่ทำให้ MACROS ชั่วร้าย : D
Nawaz

7
ฉันใช้ทั้งโปรเจ็กต์ / D "NOMINMAX"
มิ

@ มิกก้า: คุณวางตัวเลือกนี้ไว้ที่ไหนในการตั้งค่าโครงการของคุณ ฉันต้องใช้ตัวเลือกเดียวกันและฉันไม่รู้ว่าจะใส่ที่ไหน ...
flaviu2

@ flaviu2 afair ในฟิลด์ "คำสั่งเพิ่มเติม" บนหน้าที่มีการสรุปคำสั่งคอมไพล์ทั้งหมด แต่ไม่สามารถตรวจสอบได้ในขณะนี้
มิ

เพื่อเพิ่ม: #include <algorithm> + NOMINMAX
user63898

93

ไม่จำเป็นต้องกำหนดอะไรเลยเพียงข้ามมาโครโดยใช้ไวยากรณ์นี้:

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

1
ขอบคุณนี่คือวิธีแก้ปัญหาที่ได้ผลสำหรับฉัน ฉันกำลังทำงานกับโค้ดที่ฉันไม่สามารถใช้ NOMINMAX ได้เนื่องจากโค้ดบางส่วนใช้โค้ดวาดจาก Windows ที่ต้องการมาโคร
Mickaël C. Guimarães

1
คุณช่วยอธิบายได้ไหมว่าทำไมวงเล็บรอบ ๆ เวทมนตร์จึงสามารถเอาชนะมาโครที่ชั่วร้ายได้!? เจ๋ง
Chen OT

2
ฉันไม่แน่ใจเกี่ยวกับเวทมนตร์ทั้งหมดที่อยู่ภายใต้ประทุน แต่ฉันเชื่อว่าตัวแยกวิเคราะห์มาโครต้องการแทนที่ "min (" ดังนั้น "min) (" จะถูกละเว้นโดยตัวแยกวิเคราะห์แมโครและชื่อฟังก์ชันที่ถูกรวมไว้ด้วย ความหมาย () ไม่ก่อให้เกิดปัญหาใด ๆ นอกมาโคร
PolyMesh

1
วิธีแก้ปัญหาที่เรียบร้อย แต่ไม่สามารถแก้ปัญหาการมีฟังก์ชันที่มีชื่อminหรือmax(กรณีการใช้งานตัวอย่าง: การใช้คลาสที่เหมาะกับแนวคิดUniformRandomNumberGenerator )
Nik Bougalis

โปรดดูคำตอบของ Erik ฉันคิดว่ามันเป็นทางออกที่ดีกว่า แฮ็คน้อยลงและชัดเจนขึ้น
PolyMesh

28

ดังที่คนอื่นกล่าวถึงข้อผิดพลาดเกิดจากมาโคร min / max ที่กำหนดไว้ในส่วนหัวของ windows มีสามวิธีในการปิดใช้งาน

1) #define NOMINMAXก่อนที่จะรวมส่วนหัวนี่เป็นเทคนิคที่ไม่ดีในการกำหนดมาโครเพื่อให้มีผลต่อส่วนหัวต่อไปนี้

2) กำหนด NOMINMAXในบรรทัดคำสั่งคอมไพเลอร์ / IDE ส่วนที่ไม่ดีเกี่ยวกับการตัดสินใจนี้คือหากคุณต้องการจัดส่งแหล่งที่มาคุณต้องเตือนผู้ใช้ให้ทำเช่นเดียวกัน

3) เพียงแค่ยกเลิกการกำหนดมาโครในโค้ดของคุณก่อนที่จะใช้

#undef min
#undef max

นี่อาจเป็นโซลูชันแบบพกพาและยืดหยุ่นที่สุด


2
อีกปัญหาหนึ่งของตัวเลือกที่ 1 ก็คือมันไม่ได้ผลเสมอไป อาจมีส่วนหัวของหน้าต่างอื่น ๆ รวมอยู่ในที่อื่นที่ต้องการเช่น gdiplus.h ในกรณีนั้นตัวเลือกที่ 3 อาจเป็นความหวังเดียวของคุณ
shawn1874

28

ฉันยังคงมีปัญหาในบางครั้งกับส่วนหัวของหน้าต่างและการกำหนดแบบกว้างของโปรเจ็กต์ของ NOMINMAX ดูเหมือนจะไม่ได้ผลเสมอไป เพื่อเป็นทางเลือกในการใช้วงเล็บบางครั้งฉันก็กำหนดประเภทให้ชัดเจนเช่นนี้:

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

นอกจากนี้ยังหยุดตัวประมวลผลล่วงหน้าจากการจับคู่minและสามารถอ่านเนื้อหาได้มากกว่าวิธีแก้ปัญหาในวงเล็บ


3
ฉันยอมรับนี่เป็นทางออกที่ดีที่สุด ฉันเพิ่งกลับมาเพื่อให้คำตอบอีกครั้งเมื่อเห็นว่ามีคนอื่นทุบตีฉัน
PolyMesh

16

ลองทำสิ่งนี้:

#define NOMINMAX
#include <windows.h>

ตามค่าเริ่มต้น windows.h จะกำหนดminและmaxเป็นมาโคร เมื่อมีการขยายโค้ดที่พยายามใช้std::min(เช่น) จะพบสิ่งนี้:

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

ข้อความแสดงข้อผิดพลาดกำลังแจ้งให้คุณทราบstd::(x)ว่าไม่ได้รับอนุญาต


5

ในกรณีของฉันโครงการไม่ได้รวมwindows.hหรือwindef.hระบุไว้อย่างชัดเจน มันใช้ Boost ดังนั้นฉันจึงแก้ไขปัญหาโดยไปที่โครงการProperties -> C/C++ -> Preprocessorและต่อท้ายNOMINMAXในPreprocessor Definitions(VS 2013, VS 2015)


สำหรับ VS 2015 การกำหนดมาโครในไฟล์ไม่ได้ผลสำหรับฉัน การกำหนดในโครงการได้ผล
qqqqq

3

สำหรับคนที่รวม windows.h ให้ใส่สิ่งต่อไปนี้ในส่วนหัวที่มีผล:

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

ในไฟล์ต้นฉบับเพียง #undef ขั้นต่ำและสูงสุด

#include windows headers ...

#undef min
#undef max

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


2

เพื่อแก้ปัญหานี้ฉันเพิ่งสร้างไฟล์ส่วนหัวที่ชื่อfix_minmax.h โดยไม่รวมการ์ด

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

การใช้งานพื้นฐานเป็นแบบนี้

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

ข้อดีของวิธีนี้คือใช้ได้กับไฟล์ทุกประเภทหรือบางส่วนของโค้ด นอกจากนี้ยังช่วยประหยัดเวลาของคุณเมื่อต้องจัดการกับโค้ดหรือไลบรารีที่ขึ้นอยู่กับmin/ maxมาโคร


1

ฉันถือว่า windows.h กำหนด min เป็นมาโครเช่น

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

นั่นจะอธิบายข้อความแสดงข้อผิดพลาด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.