จะตรวจสอบเวอร์ชันของมาตรฐาน C ++ ที่คอมไพเลอร์ใช้อย่างไร?


116

คุณจะทราบได้อย่างไรว่าคอมไพเลอร์ของคุณใช้มาตรฐาน C ++ เวอร์ชันใด เท่าที่ฉันรู้ด้านล่างนี้คือมาตรฐานที่ฉันรู้จัก:

  • C ++ 03
  • C ++ 98

3
คุณติดแท็กc ++นี้ แต่สองในสามมาตรฐานที่คุณระบุไม่ใช่มาตรฐาน C ++ คุณสนใจภาษาใด
Rob Kennedy

1
และมีการถามคำถามเมื่อสองสามนาทีที่แล้ว ( stackoverflow.com/questions/7132440/… )
จ้า

1
@ แมท: ถูกวางและปิดเพราะคำถามเป็นขยะและมีการสำรองข้อมูลไร้สาระอื่น ๆ โดยพลการ ฉันได้โพสต์อีกครั้งในรูปแบบที่เหมาะสม ฉันยินดีที่จะปิดอันนี้หากดูเหมือนต้นฉบับจะได้รับการแก้ไขและฟื้นขึ้นมา แต่ฉันไม่ได้กลั้นหายใจ
Lightness Races ในวงโคจร

1
@ แมท: คำตอบที่ดีที่สุดไม่ใช่รายการคอมไพเลอร์แบบคงที่ แต่เป็นวิธีการพิจารณาด้วยตัวคุณเองว่ากำลังใช้อะไรอยู่ เอาล่ะ
Lightness Races ใน Orbit

1
@ แอล: มันจะเร็ว ๆ นี้ ฉันสัญญา. นอกจากนี้c++-faqแท็กไม่ได้มีจริง "จำนวนครั้งที่ถามว่า" ก่อนจำเป็นที่คุณต้องผ่าน; เป็นข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบและลักษณะทั่วไปของสิ่งนั้น
Lightness Races ในวงโคจร

คำตอบ:


13

โดยความรู้ของฉันไม่มีวิธีโดยรวมที่จะทำเช่นนี้ ถ้าคุณดูที่ส่วนหัวของแพลตฟอร์มข้าม / หลายคอมไพเลอร์สนับสนุนห้องสมุดที่คุณมักจะพบมากของที่กำหนดโครงสร้างการใช้คอมไพเลอร์ที่เฉพาะเจาะจงในการกำหนดสิ่งต่างๆเช่น:

/*Define Microsoft Visual C++ .NET (32-bit) compiler */
#if (defined(_M_IX86) && defined(_MSC_VER) && (_MSC_VER >= 1300)
     ...
#endif

/*Define Borland 5.0 C++ (16-bit) compiler */
#if defined(__BORLANDC__) && !defined(__WIN32__)
     ...
#endif

คุณอาจจะต้องกำหนดตัวเองสำหรับคอมไพเลอร์ทั้งหมดที่คุณใช้


1
ไม่ใช่คำตอบที่ฉันคาดหวัง แต่ฉันเดาว่าไม่มีวิธีสากลในการค้นหาคำตอบ
jasonline

248

จากคำถามที่พบบ่อย Bjarne Stroustrup C ++ 0x :

__cplusplus

ใน C ++ 0x แมโคร__cplusplusจะถูกตั้งค่าที่แตกต่างจาก (มีค่ามากกว่า) 199711Lในปัจจุบัน

แม้ว่าสิ่งนี้จะไม่เป็นประโยชน์อย่างที่ใคร ๆ ต้องการ gcc(เห็นได้ชัดเกือบ 10 ปี) ได้ตั้งค่านี้เป็น1คดีหนึ่งคอมไพเลอร์ที่สำคัญจนกระทั่งมันได้รับการแก้ไขเมื่อ GCC 4.7.0 ออกมา

นี่คือมาตรฐาน C ++ และคุณค่าที่คุณคาดหวังได้จาก__cplusplus:

  • C ++ pre-C ++ 98: __cplusplusคือ1.
  • C ++ 98: __cplusplusคือ199711L.
  • C ++ 98 + TR1: สิ่งนี้อ่านว่า C ++ 98 และไม่มีวิธีตรวจสอบว่าฉันรู้
  • C ++ 11: __cplusplusคือ201103L.
  • C ++ 14: __cplusplusคือ201402L.
  • C ++ 17: __cplusplusคือ201703L.

หากคอมไพเลอร์อาจเป็นรุ่นเก่าgccเราจำเป็นต้องใช้แฮ็กเกอร์เฉพาะของคอมไพเลอร์ (ดูที่มาโครเวอร์ชันเปรียบเทียบกับตารางที่มีคุณสมบัติที่ใช้งาน) หรือใช้Boost.Config (ซึ่งมีมาโครที่เกี่ยวข้อง ) ข้อดีของสิ่งนี้คือเราสามารถเลือกคุณลักษณะเฉพาะของมาตรฐานใหม่และเขียนวิธีแก้ปัญหาได้หากไม่มีคุณลักษณะดังกล่าว สิ่งนี้มักเป็นที่ต้องการมากกว่าโซลูชันการขายส่งเนื่องจากคอมไพเลอร์บางตัวจะอ้างว่าใช้ C ++ 11 แต่มีคุณลักษณะเพียงบางส่วนเท่านั้น

Stdcxx Wiki โฮสต์เมทริกซ์ที่ครอบคลุมสำหรับการสนับสนุนคอมไพเลอร์ของคุณสมบัติ C ++ 0x (ถ้าคุณกล้าที่จะตรวจสอบคุณสมบัติด้วยตัวเอง)

น่าเสียดายที่การตรวจสอบคุณสมบัติที่ละเอียดยิ่งขึ้น (เช่นฟังก์ชันไลบรารีแต่ละรายการเช่นstd::copy_if) สามารถทำได้ในระบบบิลด์ของแอปพลิเคชันของคุณเท่านั้น (รันโค้ดด้วยคุณสมบัติตรวจสอบว่าคอมไพล์และให้ผลลัพธ์ที่ถูกต้องหรือไม่ - autoconfเป็นเครื่องมือที่คุณเลือกได้หากใช้ เส้นทางนี้).


ดูเหมือนว่าผู้ขายคอมไพเลอร์กำลังอัปเดตสิ่งนี้บางทีพวกเขาอาจรอจนกว่าพวกเขาจะเป็นไปตามมาตรฐานอย่างสมบูรณ์หรือไม่ ( stackoverflow.com/q/14131454/11698 )
Richard Corden

2
@prnr: นั่นอาจจะจริง แต่ขึ้นอยู่กับผู้ใช้ที่ถามคำถามว่าจะยอมรับคำตอบใด ในขณะที่โพสต์คำตอบที่ระบุว่ายอมรับแล้วนั้นถูกต้องผู้โพสต์ต้นฉบับจึงยอมรับคำตอบนั้น ผู้ใช้รายนั้นสามารถตัดสินใจที่จะเปลี่ยนคำตอบที่ยอมรับได้ แต่อาจไม่มีการใช้งานบนไซต์อีกต่อไป ดู: meta.stackexchange.com/questions/120568/…
แดนกรณ์

3
เทียบกับ 2017 ให้มูลค่าของ __cplusplus 199711
Al Mamun

5
@AlMamun Microsoft บางส่วนได้รับการแก้ไข__cplusplusเฉพาะใน VS 15.7 ดูบล็อกทีม Visual C ++
Ivan_Bereziuk

1
ลิงก์ไปยังคำถามที่พบบ่อยเสีย
brainplot

40

โปรดเรียกใช้รหัสต่อไปนี้เพื่อตรวจสอบเวอร์ชัน

#include<iostream>

int main() {
    if (__cplusplus == 201703L) std::cout << "C++17\n";
    else if (__cplusplus == 201402L) std::cout << "C++14\n";
    else if (__cplusplus == 201103L) std::cout << "C++11\n";
    else if (__cplusplus == 199711L) std::cout << "C++98\n";
    else std::cout << "pre-standard C++\n";
}

8
มันตลกดีเพราะในสตูดิโอภาพค่าของ __cplusplus คือ 199711L และรหัสที่คุณโพสต์กลับ c ++ 98 อย่างไรก็ตามฉันได้ใช้คุณสมบัติจาก c ++ 14 รวมถึงเทมเพลตตัวแปรและประเภทการปฏิเสธ (อัตโนมัติ) เป็นไปได้ไหมว่ามีการใช้มาโครผิดเวอร์ชัน
Colin Hicks

2
ดู: devblogs.microsoft.com/cppblog/… (TLDR: ระบุแฟ/Zc:__cplusplus
Daan Timmer

@DaanTimmer ฉันสับสนกับบทความนั้นดูเหมือนว่าจะถือว่ามีความรู้ในการใช้/Zc:__cplusplusธง ฉันทำไม่ได้std::cout << /Zc:__cplusplus;เพราะเครื่องหมายโคลอนและเครื่องหมายทับไม่สามารถเป็นส่วนหนึ่งของชื่อตัวแปรได้แน่นอน คุณสามารถอธิบายวิธีการนี้ได้หรือไม่? ขอบคุณ.
A__


7

ขึ้นอยู่กับสิ่งที่คุณต้องการบรรลุBoost.Configอาจช่วยคุณได้ ไม่มีการตรวจจับเวอร์ชันมาตรฐาน แต่มีมาโครที่ให้คุณตรวจสอบการรองรับภาษา / คุณสมบัติคอมไพเลอร์ที่เฉพาะเจาะจง


3
การตรวจสอบคุณสมบัติอาจเป็นความคิดที่ดีกว่าการตรวจสอบเวอร์ชันมาตรฐานอยู่แล้ว คอมไพเลอร์เพียงไม่กี่ตัวที่รองรับทุกอย่างจากมาตรฐาน แต่ถ้าพวกเขาทั้งหมดรองรับคุณสมบัติจำนวน จำกัด ที่คุณต้องการก็ไม่สำคัญว่าคุณสมบัติที่เหลือจากมาตรฐานที่กำหนดจะถูกนำไปใช้และทำงานได้อย่างถูกต้องหรือไม่
Rob Kennedy



0

หลังจากใช้Google อย่างรวดเร็ว :

__STDC__และ__STDC_VERSION__ดูที่นี่


ไม่ว่าจะ__STDC__มีการกำหนดและสิ่งที่ค่าของมันจะมีการดำเนินการตามที่กำหนดไว้ใน C ++
Rob Kennedy

@ ร็อบ: ใช่ครับ @Tor: ฉันลองใน VC ++ 2005 แต่มันบอกว่าSTDCเป็นตัวระบุที่ไม่ได้ประกาศ มันถูกระบุว่าเป็นหนึ่งในมาโครที่กำหนดไว้ล่วงหน้าเหล่านั้น อย่างไรก็ตามไม่มีSTDC_VERSION
jasonline

สิ่งนี้จะบอกคุณถึงเวอร์ชันของการเขียนโปรแกรมภาษาซีที่คอมไพเลอร์สนับสนุน มันบอกอะไรคุณเกี่ยวกับเวอร์ชันของภาษา C ++ ที่รองรับ
Dan Moulding

0

โดยปกติคุณควรใช้การ__cplusplusกำหนดเพื่อตรวจจับ c ++ 17 แต่โดยค่าเริ่มต้นคอมไพเลอร์ของ Microsoft ไม่ได้กำหนดมาโครนั้นอย่างถูกต้องโปรดดูhttps://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - คุณต้องการ เพื่อแก้ไขการตั้งค่าโครงการเพื่อรวม/Zc:__cplusplusสวิตช์หรือคุณสามารถใช้ไวยากรณ์เช่นนี้:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.