Bagaimana cara menentukan versi standar C ++ yang digunakan oleh compiler?


115

Bagaimana Anda menentukan versi standar C ++ yang diimplementasikan oleh compiler Anda? Sejauh yang saya tahu, di bawah ini adalah standar yang saya ketahui:

  • C ++ 03
  • C ++ 98

3
Anda memberi tag pada c ++ ini , tetapi dua dari tiga standar yang Anda daftarkan bukanlah standar C ++. Bahasa apa yang Anda minati?
Rob Kennedy

1
Dan pertanyaannya baru diajukan beberapa menit yang lalu. ( stackoverflow.com/questions/7132440/… )
Mat

1
@ Mat: Berpose dan ditutup karena pertanyaan itu sampah dan ada beberapa omong kosong sembarangan lainnya. Saya telah memposting ulang dalam bentuk yang layak. Saya akan dengan senang hati menutup yang ini jika tampaknya aslinya akan diperbaiki dan dihidupkan kembali, tetapi saya tidak menahan napas.
Balapan Ringan di Orbit

1
@Mat: Jawaban terbaik bukanlah daftar statis kompiler, tetapi alat untuk menentukan sendiri apa yang sedang digunakan. Jadi begitulah.
Balapan Ringan di Orbit

1
@Als: Ini akan segera. Saya berjanji. Selain itu, c++-faqtag tidak memiliki sebenarnya prasyarat "beberapa kali meminta" bahwa Anda harus melewati; ini lebih tentang format dan keumuman hal tersebut.
Balapan Ringan di Orbit

Jawaban:


13

Sepengetahuan saya tidak ada cara keseluruhan untuk melakukan ini. Jika Anda melihat header dari lintas platform / beberapa pustaka pendukung kompilator, Anda akan selalu menemukan banyak definisi yang menggunakan konstruksi khusus kompilator untuk menentukan hal-hal seperti itu:

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

Anda mungkin harus melakukan definisi seperti itu sendiri untuk semua kompiler yang Anda gunakan.


1
Bukan jawaban yang saya harapkan, tapi saya kira tidak ada cara universal untuk mengetahuinya.
jasonline

248

Dari FAQ Bjarne Stroustrup C ++ 0x :

__cplusplus

Di C ++ 0x makro __cplusplusakan disetel ke nilai yang berbeda dari (lebih besar dari) arus 199711L.

Meskipun ini tidak membantu seperti yang diinginkan. gcc(tampaknya selama hampir 10 tahun) menetapkan nilai ini 1, mengesampingkan satu kompiler utama, hingga diperbaiki ketika gcc 4.7.0 keluar .

Ini adalah standar C ++ dan nilai apa yang seharusnya dapat Anda harapkan __cplusplus:

  • C ++ pre-C ++ 98: __cplusplusadalah 1.
  • C ++ 98: __cplusplusadalah 199711L.
  • C ++ 98 + TR1: Ini terbaca sebagai C ++ 98 dan tidak ada cara untuk memeriksa yang saya ketahui.
  • C ++ 11: __cplusplusadalah 201103L.
  • C ++ 14: __cplusplusadalah 201402L.
  • C ++ 17: __cplusplusadalah 201703L.

Jika kompilator mungkin lebih tua gcc, kita perlu menggunakan peretasan khusus kompilator (lihat makro versi, bandingkan dengan tabel dengan fitur yang diterapkan) atau gunakan Boost.Config (yang menyediakan makro yang relevan ). Keuntungannya adalah kami sebenarnya dapat memilih fitur tertentu dari standar baru, dan menulis solusi jika fitur tersebut hilang. Ini sering kali lebih disukai daripada solusi grosir, karena beberapa kompiler akan mengklaim menerapkan C ++ 11, tetapi hanya menawarkan sebagian fitur.

Stdcxx Wiki menghosting matriks komprehensif untuk dukungan kompiler fitur C ++ 0x (jika Anda berani memeriksa sendiri fiturnya).

Sayangnya, pemeriksaan fitur yang lebih detail (mis. Fungsi pustaka individual seperti std::copy_if) hanya dapat dilakukan dalam sistem build aplikasi Anda (jalankan kode dengan fitur tersebut, periksa apakah telah dikompilasi dan menghasilkan hasil yang benar - autoconfadalah alat pilihan jika mengambil rute ini).


Tidak terlihat seperti vendor kompilator memperbarui ini - mungkin mereka menunggu sampai mereka sepenuhnya sesuai dengan standar? ( Stackoverflow.com/q/14131454/11698 )
Richard Corden

2
@prnr: Itu mungkin benar, tetapi terserah pengguna yang mengajukan pertanyaan untuk memutuskan jawaban mana yang akan diterima. Pada saat jawaban yang saat ini di tandai sebagai diterima diunggah, ternyata benar, sehingga pengepos asli menerimanya. Pengguna tersebut dapat memutuskan untuk mengubah jawaban yang diterima, tetapi mereka mungkin tidak lagi aktif di situs. Lihat: meta.stackexchange.com/questions/120568/…
Dan Korn

3
vs2017 memberikan nilai __cplusplus 199711
Al Mamun

5
@AlMamun Microsoft memperbaiki sebagian __cplusplushanya di VS 15.7. Lihat Blog Tim Visual C ++ mereka
Ivan_Bereziuk

1
Tautan ke FAQ rusak.
brainplot

38

Silakan, jalankan kode berikut untuk memeriksa versi.

#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
Ini lucu, karena di studio visual nilai __cplusplus adalah 199711L dan kode yang Anda posting mengembalikan c ++ 98 namun, saya telah menggunakan fitur dari c ++ 14 termasuk templat variabel dan jenis deklarasi (otomatis). Apakah mungkin versi makro yang salah diterapkan?
Colin Hicks

2
Lihat: devblogs.microsoft.com/cppblog/… (TLDR: tentukan bendera /Zc:__cplusplus)
Daan Timmer

@DaanTimmer Saya bingung dengan artikel itu, tampaknya mengasumsikan pengetahuan tentang cara menggunakan /Zc:__cplusplusbendera. Saya tidak bisa begitu saja std::cout << /Zc:__cplusplus;karena titik dua dan garis miring tidak bisa menjadi bagian dari nama variabel tentunya. Apakah Anda dapat menjelaskan bagaimana melakukan ini? Terima kasih.
A__


7

Bergantung pada apa yang ingin Anda capai, Boost.Config dapat membantu Anda. Ini tidak menyediakan deteksi versi standar, tetapi menyediakan makro yang memungkinkan Anda memeriksa dukungan bahasa / fitur kompilator tertentu.


3
Memeriksa fitur mungkin merupakan ide yang lebih baik daripada memeriksa versi standar. Beberapa kompiler mendukung semuanya dari standar, tetapi jika mereka semua mendukung sejumlah fitur terbatas yang Anda butuhkan, maka tidak masalah apakah fitur lainnya dari standar tertentu diimplementasikan dan bekerja dengan benar.
Rob Kennedy



0

Setelah google cepat :

__STDC__dan __STDC_VERSION__, lihat di sini


Apakah __STDC__ditentukan, dan apa nilainya, ditentukan oleh implementasi dalam C ++.
Rob Kennedy

@ Rob: Ya, benar. @Tor: Saya mencoba di VC ++ 2005 tetapi dikatakan STDC adalah pengenal yang tidak dideklarasikan. Itu terdaftar sebagai salah satu makro yang ditentukan sebelumnya. Namun, STDC_VERSION tidak ada.
jasonline

Ini memberi tahu Anda versi bahasa pemrograman C yang didukung oleh kompiler. Ini tidak memberi tahu Anda tentang versi bahasa C ++ yang didukung.
Dan Moulding

0

Biasanya Anda harus menggunakan __cplusplusdefine untuk mendeteksi c ++ 17, tetapi secara default microsoft compiler tidak menentukan makro tersebut dengan benar, lihat https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - Anda perlu untuk mengubah setelan proyek untuk menyertakan /Zc:__cplusplussakelar, atau Anda dapat menggunakan sintaks seperti ini:

#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
     //C++17 specific stuff here
#endif
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.