Apakah #pragma pernah menjadi bagian dari standar C ++ 11?

140

Secara tradisional, cara standar dan portabel untuk menghindari beberapa inklusi header dalam C ++ adalah / adalah dengan menggunakan #ifndef - #define - #endifskema arahan pra-kompiler juga disebut skema penjaga makro (lihat cuplikan kode di bawah).

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

Di sebagian besar implementasi / kompiler (lihat gambar di bawah), ada alternatif yang lebih "elegan" yang memiliki tujuan yang sama dengan skema penjaga makro yang disebut #pragma once. #pragma oncememiliki beberapa keunggulan dibandingkan dengan skema penjaga makro, termasuk lebih sedikit kode, menghindari bentrokan nama, dan kadang-kadang meningkatkan kecepatan kompilasi.

masukkan deskripsi gambar di sini

Melakukan penelitian, saya menyadari bahwa meskipun #pragma oncedirektif didukung oleh hampir semua kompiler yang dikenal, ada keruh pada apakah #pragma oncedirektif merupakan bagian dari standar C ++ 11 atau tidak.

Pertanyaan:

  • Bisakah seseorang mengklarifikasi apakah #pragma oncearahan merupakan bagian dari standar C ++ 11 atau tidak?
  • Jika itu bukan bagian dari standar C ++ 11, apakah ada rencana untuk memasukkannya pada rilis nanti (mis., C ++ 14 atau lebih baru)?
  • Akan lebih baik jika seseorang dapat menguraikan lebih lanjut tentang kelebihan / kekurangan dalam menggunakan salah satu teknik (yaitu, penjaga makro versus #pragma once).
101010
sumber
9
Kebetulan, menggunakan garis bawah ganda untuk pelindung header dilarang oleh standar, bahwa cadangan untuk implementasi semua simbol dimulai dengan garis bawah ganda (selain yang lain).
Matteo Italia
9
Menggunakan garis bawah terkemuka yang diikuti dengan huruf kapital juga dilarang. Kedua, di mana kekeruhannya? Saya hanya melihat dukungan kompiler, saya melihat tidak ada yang mengklaim itu adalah bagian dari standar?
Yakk - Adam Nevraumont
1
Untuk bulletpoint ketiga, lihat pertanyaan terkait: Apakah #pragma dulunya aman termasuk penjaga? Itu punya situasi di mana penjaga header bekerja tetapi #pragma oncebiasanya tidak.
user1942027
1
duplikat mungkin dalam menjawab pertanyaan ini tanpa menyebutkan C ++ 11.
Yakk - Adam Nevraumont
3
Yah, itu tidak dikodekan dalam dokumen resmi apa pun, tetapi Anda dapat menganggapnya sebagai standar de facto .
Siyuan Ren

Jawaban:

107

#pragma onceadalah tidak standar. Ini adalah ekstensi luas (tetapi tidak universal), yang dapat digunakan

  • jika masalah portabilitas Anda terbatas, dan
  • Anda dapat yakin bahwa semua file yang disertakan selalu di disk lokal.

Itu dianggap untuk standardisasi, tetapi ditolak karena tidak dapat diimplementasikan dengan andal. (Masalah terjadi ketika Anda memiliki file yang dapat diakses melalui beberapa mount jarak jauh yang berbeda.)

Ini cukup mudah untuk memastikan bahwa tidak ada konflik penjaga termasuk dalam satu pengembangan. Untuk pustaka, yang dapat digunakan oleh banyak perkembangan yang berbeda, solusi yang jelas adalah menghasilkan banyak karakter acak untuk penjaga menyertakan saat Anda membuatnya. (Editor yang baik dapat diatur untuk melakukan ini untuk Anda setiap kali Anda membuka header baru.) Tetapi bahkan tanpa ini, saya belum pernah mengalami masalah dengan konflik antara perpustakaan.

James Kanze
sumber
11
Bukan hanya mount jarak jauh. Hardlinks, softlinks, konstruk subst (pada Windows). Itu bisa sangat berantakan.
Tonny
45
Mengapa kompiler tidak dapat menggunakan checksum SHA-1 atau MD5 untuk mengidentifikasi file?
Sergey
29
Saya benar-benar tidak melihat gunanya untuk tidak memasukkan sesuatu ke dalam standar jika setiap kompiler utama mendukungnya. Ada hal-hal yang sebenarnya dalam standar jauh kurang didukung daripada ini. Juga, agak konyol untuk mengeluh tentang masalah tepi, ketika kita berbicara tentang menyertakan file, di mana bentrokan nama file sudah menjadi masalah besar. Alangkah baiknya jika permintaan untuk fitur bebas masalah 100% ini telah diterapkan pada konsep file header #included secara umum.
TED
38
Jika kode Anda menyertakan beberapa file dari lokasi yang berbeda melalui tautan simbolis atau gunung aneh, maka itu sudah tidak portabel. Oleh karena itu berdebat bahwa pragma oncetidak dapat dengan mudah mengimplementasikan sesuatu yang secara inheren tidak portabel (dan bahkan tidak boleh dianggap) adalah omong kosong lain dari C ++ terbalik dunia.
doc
7
@JoseAntonioDuraOlmos Saya setuju bahwa tautan simbolik adalah fitur OS, yang berada di luar cakupan bahasa C ++. Oleh karena itu timbul pertanyaan mengapa C ++ comitee harus mempertimbangkan sesuatu yang berada di luar jangkauan bahasa? Mencoba untuk menjamin sesuatu yang bukan tanggung jawab mereka tidak masuk akal IMO. DOS hanya mendukung 8 + 3 karakter per nama file, namun tidak ada yang berpendapat bahwa #includeharus dihapus, karena orang dapat secara membabi buta menyalahgunakan arahan. #pragma oncetidak membatasi portabilitas dengan cara apa pun, asalkan Anda tidak akan mengeksploitasi tautan simbolik untuk memecah kompilasi.
doc
32

Bagian §16.6 dari Standar ( konsep N3936 ) menjelaskan #pragmaarahan sebagai:

Arahan preprocessing dari formulir

# pragma pp-tokensopt new-line

menyebabkan implementasi berperilaku dengan cara yang ditentukan implementasi. Perilaku ini dapat menyebabkan terjemahan gagal atau menyebabkan penerjemah atau program yang dihasilkan berperilaku dengan cara yang tidak sesuai. Setiap pragma yang tidak dikenali oleh implementasi diabaikan.

Pada dasarnya #pragma onceadalah contoh implementasi khusus dari #pragmaarahan, dan tidak, itu bukan standar. Namun.

Hal ini sering didukung secara luas oleh sebagian besar "kompiler utama" termasuk GCC dan Dentang dan oleh karena itu kadang-kadang direkomendasikan untuk menghindari boilerplate termasuk-penjaga.

Sepatu
sumber
10
Perhatikan bahwa Anda bisa keduanya #pragmadan #defineheader-guard.
Yakk - Adam Nevraumont
18
"Setiap pragma yang tidak dikenali oleh implementasi diabaikan" . Apakah itu berarti pesan: Peringatan: arahan pragma yang tidak dikenal tidak sesuai?
rodrigo
6
"Dan karena itu cara yang direkomendasikan untuk menghindari boilerplate termasuk-penjaga" - pernyataan yang sangat berani. Ini cara yang tidak standar, dan manfaat menggunakannya sedikit dan hampir tidak relevan dalam pengalaman saya, jadi saya harus mengambil +1 saya.
Alex
19
@ Yakk: Jika seseorang menulis #defineheader-guard, dia TIDAK punya alasan untuk menulis #pragma oncejuga.
Nawaz
5
@Nawaz Kompiler dapat menyimpan cache dari setiap file (dengan jalur) yang telah #pragma onced, dan jika itu #includelagi d dapat melewati #include(bahkan tidak membuka file). gcc melakukan hal yang sama dengan penjaga tajuk, tetapi sangat, sangat rapuh. Yang #pragmamudah dilakukan, yang sundulannya susah.
Yakk - Adam Nevraumont