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:
@ 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.
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.
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/…
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?
@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.
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.
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
4
__cplusplus
Dalam C ++ 0x makro __cplusplus akan disetel ke nilai yang berbeda dari (lebih besar dari) 199711L saat ini.
Gunakan __cplusplusseperti yang disarankan. Hanya satu catatan untuk kompiler Microsoft, gunakan Zc:__cplusplussaklar kompilator untuk mengaktifkan__cplusplus
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:
c++-faq
tag tidak memiliki sebenarnya prasyarat "beberapa kali meminta" bahwa Anda harus melewati; ini lebih tentang format dan keumuman hal tersebut.Jawaban:
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:
Anda mungkin harus melakukan definisi seperti itu sendiri untuk semua kompiler yang Anda gunakan.
sumber
Dari FAQ Bjarne Stroustrup C ++ 0x :
Meskipun ini tidak membantu seperti yang diinginkan.
gcc
(tampaknya selama hampir 10 tahun) menetapkan nilai ini1
, 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
:__cplusplus
adalah1
.__cplusplus
adalah199711L
.__cplusplus
adalah201103L
.__cplusplus
adalah201402L
.__cplusplus
adalah201703L
.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 -autoconf
adalah alat pilihan jika mengambil rute ini).sumber
__cplusplus
hanya di VS 15.7. Lihat Blog Tim Visual C ++ merekaSilakan, jalankan kode berikut untuk memeriksa versi.
sumber
/Zc:__cplusplus
)/Zc:__cplusplus
bendera. Saya tidak bisa begitu sajastd::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.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.
sumber
C ++ 0x FAQ oleh BS
sumber
Gunakan
__cplusplus
seperti yang disarankan. Hanya satu catatan untuk kompiler Microsoft, gunakanZc:__cplusplus
saklar kompilator untuk mengaktifkan__cplusplus
Sumber https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
sumber
Setelah google cepat :
__STDC__
dan__STDC_VERSION__
, lihat di sinisumber
__STDC__
ditentukan, dan apa nilainya, ditentukan oleh implementasi dalam C ++.Biasanya Anda harus menggunakan
__cplusplus
define 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:__cplusplus
sakelar, atau Anda dapat menggunakan sintaks seperti ini:sumber