2009-08-11 16 views
7

当初はこれが必要だと思っていましたが、結局それを避けました。しかし、私の好奇心(と知識のための食欲、ハム)私は尋ねますプリプロセッサマクロを別のプリプロセッサディレクティブに展開する

は、プリプロセッサマクロ缶例えば

#include "MyClass.h" 

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 

に別の拡大は

#include "MyClass.h" 

#include "FooTemplate.h" 
template class FooTemplate<MyClass>; 

のように、含まれますか?

+2

ある日、Linuxのような大文字と小文字が区別されるOS(例:Foo.hとfoo.hは2つの異なるファイル)にコードを転送し、Windowsで捕捉されないすべてのスペルミスが解決されます。ねぐら。あるいは、あなたがLinuxの人なら、あなたはある日、違うが同じように恐ろしい問題を抱えて、他の方法に行きたいと思うだろう。 –

+1

私は常にファイル名の小文字のルールに同意します。私は小文字変換の問題(クラス名 - >ファイル名)を除外したいので、このように書いています。しかし、それは言及する価値がある、ありがとう。 +1! – moala

+0

私たちのルールは、ファイル名が、私たちの型と関数の命名規則とまったく同じであるということです。ここではQuestionerと同じように、型名FooTypeはFooType.hで定義されます。どのような「スタイル」ガイドラインと同様に、スタイルを選択してそれに固執する。私たちがLinux上で大きく発展していると言っているので、このルールはOSによって自動的に強制されます.... hmmmmm ..... –

答えて

12

私はこれができないと信じています。これは、プリプロセッサがシングルパスであるためです。したがって、他のプリプロセッサディレクティブを発行することはできません。

具体的には、C99標準から(6.10.3.4項3):

3得られた完全 マクロ置き換え トークンシーケンスが のいずれかのような場合であっても 前処理指令として処理されていない前処理、...

興味深いことに、これが単精度_Pragma演算子がc99に追加された理由です。 #pragmaはマクロではエミットできませんでしたが、_Pragmaすることができます。

+0

もちろん、指示を出すことはもちろん可能です。それができないのは、同じプリプロセッサ・パスでそれらを処理することです。 –

+1

'#'と '## '文字はマクロ内で特別な意味を持っているので、実際に指示文をどのように出力できるかわかりません... –

+0

実際にGCCプリプロセッサは" #define X #ifdef X " #ifdefと2番目のXの間のスペースは実際には改行であり、cppを実行すると#ifdefが実際に出力されます。 –

9

C標準は、ディレクティブ( - 6.10(2) - C99前処理指令)を前処理については、これを言う:

プリプロセッサディレクティブは #前処理トークンは、(始まる前処理トークンの配列からなります変換フェーズ4の開始時) ...

と(C99 - 6.10(7)):

前処理ディレクティブ内の前処理トークンは、特に指定のない限り、マクロ の拡張の対象にはなりません。それはそれがどうなるにもかかわらず、変換フェーズ4の開始時に#で始まっていないため、2番目のライン上のトークンを前処理のシーケンスは、前処理指令ではありません

#define EMPTY 
EMPTY # include <file.h> 

:で

例マクロのEMPTYが置き換えられた後であるため、

マクロは、 '#include'前処理ディレクティブに展開できません。これらの指令は、翻訳フェーズ4の開始時(その指令を処理するときに前処理が行われるとき)に配置する必要があります。マクロ展開はフェーズ4の間に発生するので、マクロはフェーズの開始時に存在する何かを起こすことはできません4.

私は、次の作業していること、しかし、指摘したいと思います:

#ifdef WIN32 
#define PLATFORM_HEADER "platform/windows/platform.h" 
#else 
#define PLATFORM_HEADER "platform/linux/platform.h" 

#include PLATFORM_HEADER 

C標準がこれを言っているので(C99、6.10。2(4) - ソースファイルを含める):

形態

# include pp-tokens new-line 

のプリプロセッサディレクティブが(つまり、前の2つの形式のいずれかと一致しない)、許可されています。ディレクティブに含まれる前処理の トークンは、通常のテキストと同様に処理されます。 (現在マクロ名として定義された各 識別子が 前処理字句のその置換リストに置き換えられます。)

+0

私は標準のその部分を見ましたが、私はそれが最も関連性の高いセクションではないと思います。この例は、ディレクティブを発行しようとするものではありません。代わりに、 "空白"(EMPTYマクロが空白に解決されているにもかかわらず)によって先行されないディレクティブの例です。 –

+1

私は、標準からのあなたの見積もりがより直接的に関連していることに同意しますが、私が答えたときはそこにいません。上記の例が尋ねられたものと同じではない場合でも、フェーズ4の開始時に必要な前処理ディレクティブについてのビットは、マクロが6.10.3.4(3)の場合でもマクロが有用な前処理ディレクティブに展開することを禁止します。もっと直接的に言います。 (言い換えれば、私の答えが間違っているとは思わないとしても、あなたの答えは明らかに良い答えです)。 –

+0

十分に公正な、あなたは良い点を作る、+1 :-)。 –

1

すべてのプリプロセッサディレクティブは、マクロ展開が始まる前に解釈されているので、いや、あなたはマクロが#に展開することはできませんインクルードディレクティブをそのように解釈する必要があります。代わりに、(間違った)C++コードとして解釈されます。

+0

多くのディレクティブが引数のマクロ展開を無効にするため、この印象を受ける可能性がありますが、これは当てはまりません。マクロの展開はディレクティブの解析と同時に行われます。それが本当であれば、#ifはうまくいかず、#undefは人々が期待する効果を持たないでしょう。 – zwol

関連する問題