10

次のようなコード例を考えてみましょう (これは、defineとを組み合わせる人工的な例にすぎtemplateません。意味を探らないでください):

#define COMMA ,

template <typename A> class Test
{
public:
    Test(){}

    void Foo(A var COMMA int test);
};

Test<int> Knarz;

質問:

最初にプリプロセッサが COMMA のすべての出現を検索/置換し、次にコンパイラがその順序でテンプレートをインスタンス化するという私の仮定は正しいですか?

ファローアップ:

上記の答えが「はい」の場合、そうであることを願っていますが、テンプレートと定義を使用したこのソリューションが機能する理由を説明できますか?

4

4 に答える 4

13

プリプロセッサはコンパイル自体が完了する前に実行されるため、テンプレートがインスタンス化される前にプリプロセッサが置き換えられるという仮定COMMAは正しいです。

フォローアップのために: このソリューションは、テンプレートとはほとんど関係ありません。問題は、プリプロセッサが中かっこ内のコンマをマクロの引数セパレータとして使用することです。これは、C++ コードを解析して、それがテンプレート引数のセパレータであることを確認しないためです。したがって、COMMAマクロは、が置換され,た後にのみ、テンプレート引数を分離するために を挿入するために使用されます。MOCK_CONSTANT_METHOD0ただし、メモリによるマクロ置換の順序の保証がわからないため、これが機能することが保証されているかどうかはわかりません。COMMAすべてがバラバラになる前に置き換えMOCK_CONSTANT_METHOD0られ、コードが再びコンパイルされない場合。

MOCK_CONSTANT_METHOD0編集:標準を調べた後、プリプロセッサが最初に見つけて置き換えるため、ソリューションは一般的に機能するはずだと思います。そうして初めて、置換の結果を調べてCOMMAマクロを見つけます。保証はありませんが。

于 2012-04-18T11:21:02.567 に答える
3

最初のマクロとその後のテンプレート、実際にはマクロはコンパイル前に既存のコードに変更を適用するだけです。したがって、このソリューションでは、カンマは次のようなテンプレート コードを生成します。

MOCK_CONSTANT_METHOD0(aMethod, const QMap<QString,QString>());

コンパイル前。

2 番目の質問については、次のとおりです。

これは、gmock フレームワークが実際にどのように機能するかに関連しています。MOCK_CONSTANT_METHOD0 はマクロであるため、行は別のものに変換されます。Markus Mayr は、コンマはパラメーターの区切り記号として変換されるため、この場合 gmock マクロがどのように変換されるかに関連していると述べました。最初にモック マクロが置き換えられ、コンマが内部的に適用された後に、これがコンマだけでなく、マクロでも機能する理由。

于 2012-04-18T11:20:49.760 に答える
1

プリプロセッサが最初です。

参照されているソリューションは、プリプロセッサが置換を実行する順序に依存するため、かなり悪い考えだと思います。シャレード全体は、プリプロセッサがテンプレート引数リストのコンマを詰まらせるのを防ぐためにのみ使用されるため、typedef を使用する方がはるかに優れています。

于 2012-04-18T11:21:37.980 に答える
0

There are 9 phases of translation.

Is my assumption correct that, first the preprocessor will search/replace all occurrences of COMMA and second the compiler will instantiate any templates in that order?

The COMMA token is substituted in phase 4.
The templates are instantiated in phase 8.

于 2016-06-25T18:55:06.033 に答える