2011-03-04 13 views
7

ガードが存在し、私の質問は、異なる種類のものである ガードを含めたくない状況はありますか?

#pragma onceは標準ではありませんので、すべてのコンパイラでサポートされていないなどということが含まれ、なぜ私が知っている:

は今までにそれらを持っていないために何らかの賢明な理由があります?私は理論的に、どこか他の場所にインクルードされることになっているファイルにインクルードガードを提供しないという利点があります。誰かがそれを持たないという実際の利点がある例を持っていますか?

あなたがいつも使っているように、彼らはかなり冗長に思えますし、#pragma onceの挙動は文字通りすべてに自動的に適用されます。

答えて

8

私は、インクルード前に定義されたマクロに応じてコードを生成するヘッダを見ました。この場合、それらのマクロを1つの値に定義し、ヘッダを組み込み、マクロを再定義して、再度インクルードしたいと思うことがあります。
このように見えるのは誰もが、醜くて避けがたいと同意しますが、(ヘッダーのコードが他の手段によって生成されているように)それを行うのはそれほど難しくありません。

それ以外は、私は理由を考えることができません。

+0

私は(これは、しばらく前から、多分それは今変わったのさ)FFTWライブラリにこの特定の使用に遭遇しました。いくつかの関数はin、double、floatなどのさまざまな基底型に対して作成できるように定義されているため、必要な数だけ型を定義してファイルを再インクルードすることができます。しかし、これはCライブラリです。 C++ではもちろんテンプレートを使用しています。 –

+0

@the_mandrill:C++では、テンプレートが問題に合わない状況で実際に使用されています。特にboostプリプロセッサライブラリでは、0,1,2 ... N個の引数を持つ 'boost :: bind'のように、異なる数の引数を使って同じコードを自動的に生成します。 –

+0

@DavidRodríguez:私が理解する限り、boost :: bindは最大9個の引数に対して適切なテンプレートを提供することで実装されています。編集:私は、戻り値の型(戻り値の型がvoidの場合)としてテンプレート引数を持つ関数で 'return x'状況を避けるためにboostを実行する場所を見つけましたが、私はいつも特定のテンプレートの特殊化タイプ 'void'の場合それらはインクルードガードなしでルートに行きますが、この問題を解決するために 'return'マクロを再定義する必要はありません。 – Mephane

0

同じインクルードガードを使用するプロジェクトに2つのヘッダーがあると問題になることがあります。サードパーティのライブラリが2つあり、両方にインクルードガードシンボル(__CONSTANTS_H__など)を使用するヘッダーがある場合は、指定したコンパイル単位で両方のヘッダーを正常に#includeできなくなります。より良い解決策は#pragma onceですが、古いコンパイラの中にはこれをサポートしていないものがあります。

+2

さらに、 '#pragma once' ___は標準___ではないので、コンパイラの次のバージョンがそれをサポートしているか、同じセマンティクスをサポートするという保証はありません。私にとって、それはそれを使用しないことが非常に良い理由です。 – sbi

+1

@sbi:true - 携帯性と上記で説明したような問題との間にトレードオフがあります。コンパイラとコンパイラのバージョンをテストし、それに応じてガードまたは '#pragma once 'を使用することで、いつも醜い定型文を得ることができると思いますが、すべてのヘッダでそれを確認したいとは思いません。 –

+0

2人のガードが衝突した場合、そのうちの1人を変更して、省略しないでください。 – Mephane

0

サードパーティライブラリがあり、そのコードを変更できないとします。今、このライブラリからのファイルを含めてコンパイラの警告を生成するとします。あなたは通常、高い警告レベルで独自のコードをコンパイルしたいと思いますが、そのようにすると、ライブラリを使用して大きな警告が生成されます。あなたはサードパーティのライブラリを囲むことができる警告disabler/enablerヘッダを書くことができ、それらは複数回組み込むことができるはずです。 http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

+0

このラッパーにガードを含めても何の違いもありません。既にラッパーをインクルードしていれば、* have *インクルードのサードパーティーヘッダーの警告は無効になります。そして、ラッパーを2回目にインクルードガードがキャッチして、何もインクルードしません。 – Mephane

+0

@Mephane:これは、警告ガードされていないライブラリヘッダではなく、インクルードガードなしで実行されるコンパイラ固有の警告制御プラグマを含むヘッダです。 –

3
<cassert> 
<assert.h> 

「assertマクロは、NDEBUGの現在の状態 < assert.h>が含まれていることを各時間に応じて再定義されています

使用する他のより洗練された種類は、ブーストのプリプロセッサの繰り返し構造です。 "

4

@sbiはすでにコード生成について話していますので、例を挙げておきます。

あなたは多くの項目の列挙を持っていることを言うと、あなたはその要素のそれぞれの機能の束を生成したいと...

一つの解決策は、この複数の包含トリックを使用することです。

// myenumeration.td 
MY_ENUMERATION_META_FUNCTION(Item1) 
MY_ENUMERATION_META_FUNCTION(Item2) 
MY_ENUMERATION_META_FUNCTION(Item3) 
MY_ENUMERATION_META_FUNCTION(Item4) 
MY_ENUMERATION_META_FUNCTION(Item5) 

その後、人々はそうのようにそれを使用する:これは素敵またはハックであるかどうか

#define MY_ENUMERATION_META_FUNCTION(Item_) \ 
    case Item_: return #Item_; 

char const* print(MyEnum i) 
{ 
    switch(i) { 
    #include "myenumeration.td" 
    } 

    __unreachable__("print"); 
    return 0; // to shut up gcc 
} 

#undef MY_ENUMERATION_META_FUNCTION 

はあなた次第ですが、明らかにすべてのユーティリティ機能を介して時間をクロールする必要がない便利です新しい値が列挙型に追加されます。

+0

そして、 '#define MY_ENUMERATION_META_FUNCTION'を一番上のmyenumeration.tdに置くと、2回目のファイル* once *をインクルードすることができます。あなたの例は、簡単に回避できる任意の循環インクルード依存性のように見えます。私が間違っているなら、私を修正してください。 – Mephane

+0

@Mephane:「enumeration.td」には何も含まれていないので、循環的な依存関係はどうなっているのでしょうか...また、マクロMY_ENUMERATION_META_FUNCTIONは列挙ファイルに定義されていませんそのメタ機能としての使用、それはちょっとそこにそれを定義する目的を破るだろう。 –

+0

ああ、今私はそれを参照してください。 2番目のファイルは、再利用するコードを持つ別のヘッダーではなく、実際の実装であり、それぞれの実装では独自のバージョンの 'MY_ENUMERATION_META_FUNCTION'を定義しています。そして、はい、それは完全にハックのように感じます。このようなことをすることができるかどうかは、実際のメリットであるかどうかは、むしろ主観的ではありますが、今はその可能性を見ています。 – Mephane

0

#pragma onceの問題とそれが標準の一部ではない理由は、どこでも常に動作するとは限りません。コンパイラは、異なるパスから2つのファイルが同じファイルであるかどうかを知っていますか?

コンパイラが間違いを犯して含めるべきファイルを含めることができないとどうなりますか?それが持ってはならないファイルが2回含まれているとどうなりますか?どのようにそれを修正しますか?

ガードが含まれていると、最悪の場合、コンパイルに少し時間がかかります。

編集: このスレッドをcomp.std.C++でチェックしてください。 "ISO規格ではまだ#pragma once?"

http://groups.google.com/group/comp.std.c++/browse_thread/thread/c527240043c8df92

+0

私は '#pragma once'と'#define'インクルードガードの違いについては特に質問していませんでしたが、ファイルを複数回インクルードしたい場合には特にそうです。 – Mephane

+0

私はなぜデフォルトでどこに '#pragma once 'がないのか尋ねたと思いました。最後の文のように... –

+0

私は希望の効果についてもっと尋ねていました。 '#pragma once'はインクルードガードと同様にその効果を達成する手段です。 – Mephane

関連する問題