#pragmaはC ++ 11標準の一部でしたか?


140

従来、C ++での複数のヘッダーのインクルードを回避する標準的で移植可能な方法は、マクロガードスキーム#ifndef - #define - #endifとも呼ばれるプリコンパイラディレクティブスキームを使用することでした(現在のコードスニペットを参照)。

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

ただし、ほとんどの実装/コンパイラ(下の図を参照)では、と呼ばれるマクロガードスキームと同じ目的で使用できる、より「エレガントな」代替手段があります#pragma once#pragma onceマクロガードスキームと比較して、コードの削減、名前の衝突の回避、場合によってはコンパイル速度の向上など、いくつかの利点があります。

ここに画像の説明を入力してください

調査を行ったところ、#pragma onceほとんどすべての既知のコンパイラーでディレクティブがサポートされています#pragma onceが、ディレクティブがC ++ 11標準の一部であるかどうかがわかりません。

質問:

  • 誰か#pragma onceがC ++ 11標準の一部であるかどうかを誰かが明確にできますか?
  • C ++ 11標準の一部ではない場合、それを今後のリリース(C ++ 14以降など)に含める予定はありますか?
  • また、誰かがいずれかの手法(つまり、マクロガードと#pragma once)を使用する際の利点/欠点についてさらに詳しく説明できるとよいでしょう。

9
ちなみに、ヘッダーガードにダブルアンダースコアを使用することは規格によって禁止されています。規格では、ダブルアンダースコアで始まるすべてのシンボルが実装に予約されています(他のものに加えて)。
Matteo Italia

9
先頭のアンダースコアの後に大文字を続けることも禁止されています。第二に、濁りはどこですか?私はコンパイラのサポートを見ているだけですが、それが標準の一部であると主張している人はいませんか?
Yakk-Adam Nevraumont 2014年

1
3番目の箇条書きについては、関連する質問を参照してください。#pragmaは安全なインクルードガードですか?ヘッダーガードが機能するが、#pragma once通常は機能しない状況が発生しました。
user1942027

1
C ++ 11に言及せずにこの質問に答えるという点で重複の可能性があります。
Yakk-Adam Nevraumont 2014年

3
まあ、それは公式文書にはコード化されていませんが、事実上の標準と見なすことができます。
Siyuan Ren 2014

回答:


107

#pragma onceではない標準で。これは広く使われている(ただし普遍的ではない)拡張であり、使用できます。

  • 移植性の懸念が限られている場合
  • すべてのインクルードファイルが常にローカルディスク上にあることを確認できます。

標準化のために検討されましたが、確実に実装できないため拒否されました。(この問題は、複数の異なるリモートマウントを介してファイルにアクセスできる場合に発生します。)

単一の開発内でインクルードガードの競合が発生しないようにするのはかなり簡単です。多くの異なる開発で使用される可能性があるライブラリの場合、明白な解決策は、作成時にインクルードガード用に多数のランダムな文字を生成することです。(新しいヘッダーを開くたびに、これを行うように優れたエディターを設定できます。)しかし、これがなくても、ライブラリ間の競合に関する問題はまだ発生していません。


11
リモートマウントだけではありません。ハードリンク、ソフトリンク、substコンストラクト(Windows)。それは本当に厄介になることができます。
Tonny

45
コンパイラがSHA-1またはMD5チェックサムを使用してファイルを識別できないのはなぜですか?
セルゲイ

29
すべての主要なコンパイラーが標準をサポートしているのであれば、標準に何かを入れないことには意味がありません。実際には、標準よりはるかにサポートされていないものがあります。また、ファイル名の衝突がすでに大きな問題となっているインクルードファイルについて話しているとき、エッジの問題について不平を言うのはかなりばかげているように見えます。この100%問題のない機能に対する需要が、#includedヘッダーファイルの概念全般に適用されていれば、すばらしいことでした。
TED

38
コードに、シンボリックリンクまたは奇妙なマウントを介して異なる場所からのファイルが含まれている場合、そのファイルはすでに移植可能ではありません。したがって、pragma once本質的に移植性がない(そして考慮すべきではない)ものを移植可能に実装できないと主張することは、C ++の逆さまの世界のもう1つのナンセンスです。
文書化

7
@JoseAntonioDuraOlmosシンボリックリンクはOSの機能であり、C ++言語の範囲外であることに同意します。したがって、C ++コミティが言語の範囲外のものを検討する必要があるのはなぜですか?彼らの責任ではない何かを保証しようとしても、IMOには意味がありません。DOSはファイル名ごとに8 + 3文字しかサポートしていません#includeが、盲目的にディレクティブを誤用する可能性があるため、削除する必要があると主張する人はいません。#pragma onceシンボリックリンクを利用してコンパイルを中断しない限り、移植性はまったく制限されません。
文書化

32

規格のセクション16.6(N3936ドラフト)は、#pragma指令を次のように説明しています。

次の形式の前処理指令

# pragma pp-tokensopt new-line

実装が実装定義の方法で動作するようにします。この動作により、変換が失敗したり、変換プログラムまたは結果のプログラムが非準拠で動作したりする場合があります。実装で認識されないプラグマは無視されます。

基本的に #pragma onceは、実装固有のインスタンスです。#pragmaディレクティブの標準ではありません。まだ。

多くの場合、GCCClangを含むほとんどの「主要コンパイラ」で広くサポートされているため、インクルードガードのボイラープレートを回避することが推奨される場合があります。


10
#pragma#defineヘッダーガードの両方を使用できることに注意してください。
Yakk-Adam Nevraumont 2014年

18
「実装で認識されないプラグマは無視されます」。それは、メッセージ:警告:認識されないプラグマディレクティブが準拠していないことを意味しますか?
ロドリゴ2014年

6
「したがって、インクルードガードのボイラープレートを回避するための推奨される方法です」-非常に大胆な声明。これは非標準的な方法であり、それを使用する利点はほとんどなく、私の経験にはほとんど関係がなかったため、+ 1を削除する必要がありました。
アレックス

19
@Yakk:誰かが#defineヘッダーガードを書いた場合、彼/彼女#pragma onceも同様に書く理由がありません。
Nawaz

5
@Nawazコンパイラーは、#pragma oncedであったすべてのファイル(パスによる)のキャッシュを保持できます。また、dである場合#include#include(ファイルを開くことさえせずに)スキップできます。 gccは同じことをしますヘッダーガードでも行いますが、非常に脆弱です。#pragma1が行うのは簡単ですが、ヘッダーガード1は難しいです。
Yakk-Adam Nevraumont 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.