Làm thế nào để xác định phiên bản của tiêu chuẩn C ++ được trình biên dịch sử dụng?


114

Làm cách nào để xác định phiên bản của tiêu chuẩn C ++ được trình biên dịch của bạn thực hiện? Theo như tôi biết, dưới đây là các tiêu chuẩn tôi đã biết:

  • C ++ 03
  • C ++ 98

3
Bạn đã gắn thẻ c ++ này , nhưng hai trong số ba tiêu chuẩn bạn liệt kê không phải là tiêu chuẩn C ++. Bạn quan tâm đến (các) ngôn ngữ nào?
Rob Kennedy

1
Và câu hỏi vừa được đặt ra cách đây vài phút. ( stackoverflow.com/questions/7132440/… )
Mat

1
@Mat: Đặt và đóng vì câu hỏi là rác rưởi và có một số tùy tiện vô nghĩa khác trên đó. Tôi đã đăng lại với hình thức đàng hoàng. Tôi rất vui khi đóng cái này nếu có vẻ như bản gốc sẽ được sửa và hồi sinh, nhưng tôi không nín thở.
Các cuộc đua ánh sáng trong quỹ đạo

1
@Mat: Chà, câu trả lời tốt nhất không phải là một danh sách tĩnh các trình biên dịch, mà là một phương tiện để bạn tự xác định những gì đang được sử dụng. Vậy là xong.
Các cuộc đua ánh sáng ở Orbit

1
@Als: Sẽ sớm thôi. Tôi hứa. Bên cạnh đó, c++-faqthẻ không có bất kỳ "số lần được yêu cầu" thực tế nào mà bạn phải vượt qua; nó thiên về định dạng và tính tổng quát của sự vật.
Các cuộc đua ánh sáng trong quỹ đạo

Câu trả lời:


13

Theo hiểu biết của tôi không có cách tổng thể để làm điều này. Nếu bạn nhìn vào tiêu đề của các thư viện hỗ trợ nhiều nền tảng / nhiều trình biên dịch, bạn sẽ luôn tìm thấy rất nhiều định nghĩa sử dụng các cấu trúc cụ thể của trình biên dịch để xác định những thứ như vậy:

/*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

Bạn có thể sẽ phải tự định nghĩa như vậy cho tất cả các trình biên dịch mà bạn sử dụng.


1
Mặc dù không phải là câu trả lời mong đợi của tôi nhưng tôi đoán không có cách nào phổ biến để tìm ra nó.
jasonline

246

Từ Câu hỏi thường gặp về Bjarne Stroustrup C ++ 0x :

__cplusplus

Trong C ++ 0x, macro __cplusplussẽ được đặt thành một giá trị khác với (lớn hơn) hiện tại 199711L.

Mặc dù điều này không hữu ích như người ta muốn. gcc(dường như trong gần 10 năm) đã đặt giá trị này 1, loại trừ một trình biên dịch chính, cho đến khi nó được sửa khi gcc 4.7.0 ra mắt .

Đây là các tiêu chuẩn C ++ và giá trị nào bạn có thể mong đợi __cplusplus:

  • C ++ trước C ++ 98: __cplusplus1.
  • C ++ 98: __cplusplus199711L.
  • C ++ 98 + TR1: Cái này đọc là C ++ 98 và không có cách nào để kiểm tra mà tôi biết.
  • C ++ 11: __cplusplus201103L.
  • C ++ 14: __cplusplus201402L.
  • C ++ 17: __cplusplus201703L.

Nếu trình biên dịch có thể cũ hơn gcc, chúng tôi cần phải sử dụng đến hackery cụ thể của trình biên dịch (xem macro phiên bản, so sánh nó với một bảng có các tính năng được triển khai) hoặc sử dụng Boost.Config (cung cấp các macro có liên quan ). Ưu điểm của việc này là chúng tôi thực sự có thể chọn các tính năng cụ thể của tiêu chuẩn mới và viết giải pháp thay thế nếu tính năng bị thiếu. Điều này thường được ưu tiên hơn giải pháp bán buôn, vì một số trình biên dịch sẽ yêu cầu triển khai C ++ 11, nhưng chỉ cung cấp một tập hợp con các tính năng.

Wiki Stdcxx lưu trữ một ma trận toàn diện để hỗ trợ trình biên dịch các tính năng C ++ 0x (nếu bạn dám tự mình kiểm tra các tính năng).

Thật không may, việc kiểm tra các tính năng chi tiết hơn (ví dụ: các chức năng thư viện riêng lẻ như std::copy_if) chỉ có thể được thực hiện trong hệ thống xây dựng của ứng dụng của bạn (chạy mã với tính năng, kiểm tra xem nó có được biên dịch và tạo ra kết quả chính xác không - autoconflà công cụ được lựa chọn nếu sử dụng tuyến đường này).


Có vẻ như các nhà cung cấp trình biên dịch đang cập nhật điều này - có thể họ đang đợi cho đến khi chúng hoàn toàn phù hợp với tiêu chuẩn? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden

2
@prnr: Điều đó có thể đúng, nhưng người dùng đặt câu hỏi quyết định chấp nhận câu trả lời nào là tùy thuộc vào người dùng. Tại thời điểm câu trả lời hiện được đánh dấu là chấp nhận được đăng, nó chính xác, vì vậy người đăng ban đầu đã chấp nhận nó. Người dùng đó có thể quyết định thay đổi câu trả lời được chấp nhận, nhưng họ có thể không còn hoạt động trên trang web. Xem: meta.stackexchange.com/questions/120568/…
Dan Korn

3
vs2017 mang lại giá trị của __cplusplus 199711
Al Mamun

5
@AlMamun Microsoft __cpluspluschỉ sửa một phần trong VS 15.7. Xem Blog của Nhóm Visual C ++
Ivan_Bereziuk

1
Liên kết đến Câu hỏi thường gặp bị hỏng.
brainplot

38

Vui lòng chạy mã sau để kiểm tra phiên bản.

#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
Thật buồn cười, bởi vì trên studio trực quan, giá trị của __cplusplus là 199711L và mã bạn đã đăng trả về c ++ 98. Tuy nhiên, tôi đã sử dụng các tính năng từ c ++ 14 bao gồm các mẫu biến và kiểu khai báo (tự động). Có thể phiên bản macro đã được triển khai sai không?
Colin Hicks

2
Xem: devblogs.microsoft.com/cppblog/… (TLDR: chỉ định cờ /Zc:__cplusplus)
Daan Timmer

@DaanTimmer Tôi đang bối rối bởi bài viết đó, nó dường như giả sử kiến ​​thức về cách sử dụng /Zc:__cpluspluscờ. Tôi không thể đơn giản std::cout << /Zc:__cplusplus;vì tất nhiên dấu hai chấm và dấu gạch chéo không thể là một phần của tên biến. Bạn có thể giải thích làm thế nào để làm điều này? Cảm ơn.
A__


7

Tùy thuộc vào những gì bạn muốn đạt được, Boost.Config có thể giúp bạn. Nó không cung cấp khả năng phát hiện phiên bản chuẩn, nhưng nó cung cấp các macro cho phép bạn kiểm tra sự hỗ trợ của ngôn ngữ / tính năng trình biên dịch cụ thể.


3
Kiểm tra các tính năng có lẽ là một ý tưởng tốt hơn so với kiểm tra các phiên bản tiêu chuẩn. Rất ít trình biên dịch hỗ trợ mọi thứ từ một tiêu chuẩn, nhưng nếu tất cả chúng đều hỗ trợ một số tính năng hạn chế mà bạn cần, thì việc phần còn lại của các tính năng từ một tiêu chuẩn nhất định có được triển khai và hoạt động chính xác hay không không thực sự quan trọng.
Rob Kennedy,



0

Sau khi google nhanh :

__STDC____STDC_VERSION__, xem ở đây


Việc __STDC__có được định nghĩa hay không và giá trị của nó là gì, đều được thực thi xác định trong C ++.
Rob Kennedy,

@Rob: Đúng vậy. @Tor: Tôi đã thử trong VC ++ 2005 nhưng nó nói rằng STDC là một định danh chưa được khai báo. Mặc dù vậy, nó được liệt kê là một trong những macro được xác định trước. Tuy nhiên, STDC_VERSION không tồn tại.
jasonline

Điều này cho bạn biết phiên bản của ngôn ngữ lập trình C được hỗ trợ bởi trình biên dịch. Nó không cho bạn biết gì về phiên bản của ngôn ngữ C ++ được hỗ trợ.
Dan Molding

0

Thông thường, bạn nên sử dụng __cplusplusđịnh nghĩa để phát hiện c ++ 17, nhưng theo mặc định, trình biên dịch microsoft không xác định đúng macro đó, hãy xem https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - bạn cần để sửa đổi cài đặt dự án để bao gồm /Zc:__cpluspluscông tắc hoặc bạn có thể sử dụng cú pháp như sau:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.