为什么宏扩展遵循模板扩展?

时间:2012-11-16 21:51:39

标签: c++ templates c-preprocessor

通常,首先是代码示例:

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编译。

我的问题是:

为什么宏扩展遵循模板扩展?我认为这是极端反直觉和容易出错的。

2 个答案:

答案 0 :(得分:8)

  

为什么宏扩展会遵循模板扩展?

嗯,它没有。宏扩展由预处理器完成,模板扩展由解析器/编译器阶段完成(在预处理之后仅运行)。

你在这里缺少的是宏的风格。 f2()是一个函数式宏。因此,如果您编写f2(没有括号),预处理器将不会将其替换为f1。如果您想要这样的替换,只需将其定义为

即可
#define f2 f1

旁注:正如目前的情况一样,这段代码没有多大意义。即使您使用了括号并写了f2(),也会出现编译器错误,因为f2()宏只接受一个参数。如果它是一个具有参数且不是可变参数的函数式宏,则应该为它提供一个参数。

答案 1 :(得分:4)

它没有。

问题是您使用函数式宏定义定义了f2,例如

#define f2(foo) bar

但在您的源代码中,您只使用f2作为令牌,而不是将其用作函数调用,例如

f3(f2)

由于您并未将其用作函数调用,因此它与函数式宏定义不匹配,因此无法替换。