2017-10-23 12 views
0

私は自分のアプリケーションに使用するtypedefを構築するためにマクロを展開する必要があります。マクロは単純なtypedefを構築します。私が持っている質問は何ですか?__VA_ARGS__(つまり、引数をもっと遠くまで失っていますか?)多数のマクロに渡されたときの動作と、それが正しい結果を出すために別のスキャンが必要なときを知る方法です。高次のマクロを作成するときの問題DERIVEDマクロ。 Cプリプロセッサ(MSVC++、MSVC)のマクロを正しく展開する方法は?

#define DERIVED0()   rtti::impl::BaseTypedefList<rtti::impl::null> 
#define DERIVED1(T1)  rtti::impl::BaseTypedefList<T1, DERIVED0()> 
#define DERIVED2(T1, T2) rtti::impl::BaseTypedefList<T1, DERIVED1(T2)> 
#define BUILD(count, ...) DERIVED##count(__VA_ARGS__) 

// inside the classes 
#define CLASS_BODY(count, ...) typedef BUILD(count, __VA_ARGS__) BaseClassList; 

// example usages 
CLASS_BODY(0)     // WORKS 
CLASS_BODY(1, MeshRenderer)  // WORKS 
CLASS_BODY(2, Renderer, Object) // ERROR 
+0

MSVSを使用していますか? –

+0

@HWaltersはい私はMSVSを使用しています – Matthew

答えて

1

のMicrosoft Visual Studioのバージョンは、そうでない場合は、単一のトークンにチャンクされた複数のトークンの一連のだろうエンティティの独特の概念を持っています。これは、可変的なマクロを展開するときに特に有効になります。 __VA_ARGS__は、その展開にカンマが含まれていても、常に単一のトークンとして展開されます。この現象は、Microsoftプリプロセッサ特有の現象です。特に

CLASS_BODY(2, Renderer, Object)の呼び出し中に、あなたが起動している:

BUILD(2, Renderer, Object) 

を技術的には、ここで、Renderer, Objectは1つのトークンですが、この時点でそれは問題ではありません。ここでの引数の識別中にclass2...Renderer, Objectと一致します。引数の置換時には、これが独特の何か次のようになります。

DERIVED##count(Renderer, Object) 

十分に無害に見えますが、独特の事はRenderer, Objectをまとめつのトークンであるということです。コンマはセパレータとして処理されません。含意は少し後で見ることができます...私たちは、ペーストを歩く後:

DERIVED2(Renderer, Object) 

...その後DERIVED2が呼び出されます。ここで、引数の識別はT1と一致し、Renderer, Objectと一致します。 T2がぶら下がっています。それは一致しません。これにより、プリプロセッサエラーが発生します。

ここでは、代替リストで__VA_ARGS__を使用している場合は、少なくとも複数のプリプロセッサトークンとして解析されている複数のパラメータに依存している場合に展開手順を適用することになります(ただし、このような場合は、MSVSの特質に固定されます)。間接のこのフォームは仕事と時間の99%は:機会に

#define EVAL(...) __VA_ARGS__ 
#define BUILD(count, ...) EVAL(DERIVED##count(__VA_ARGS__)) 

あなたはこのような何かをしなければならないことがあります。

#define CALL(X,Y) X Y 
#define BUILD(count, ...) CALL(DERIVED##count,(__VA_ARGS__)) 

のどちらかが、この特定のケースで動作します。

+0

これは完璧に動作しました!!!!非常に迷惑マクロは非常に異なる動作 – Matthew

関連する問題