1

原則として、最初にコード例を示します。

void f1(int)
{}

#define f2(a) f1(a)

template<class F>
void f3(F f)
{
    f(0);
}

int main()
{
    f3(f2); // error C2065: 'f2' : undeclared identifier
    return 0;
}

VC++ 2012 でコンパイル。

私の質問は:

マクロ展開がテンプレート展開に続くのはなぜですか? それは非常に直感に反し、間違いを起こしやすいと思います。

4

2 に答える 2

8

マクロ展開がテンプレート展開に続くのはなぜですか?

ええと、そうではありません。マクロの展開はプリプロセッサによって行われ、テンプレートの展開はパーサー/コンパイラ ステージ (前処理後にのみ実行される) によって行われます。

ここで見逃しているのは、マクロのスタイルです。f2()関数スタイルのマクロです。したがって、f2(括弧なしで)書くと、プリプロセッサはそれを に置き換えませんf1。そのような置換が必要な場合は、次のように定義するだけです

#define f2 f1

補足: 現在のところ、このコードはあまり意味がありません。括弧を使用して を記述したとしても、マクロは引数を 1 つだけ取るf2()ため、コンパイラ エラーが発生します。f2()引数を持ち、可変長ではない関数スタイルのマクロである場合は、それに引数を指定する必要があります。

于 2012-11-16T21:54:19.650 に答える
4

そうではありません。

問題はf2、関数スタイルのマクロ定義を使用して定義したことです。

#define f2(foo) bar

ただし、ソースコードではf2、トークンとしてのみ使用しており、関数呼び出しとしては使用していません。

f3(f2)

関数呼び出しとして使用していないため、関数スタイルのマクロ定義と一致せず、置換されません。

于 2012-11-16T21:54:21.787 に答える