宏连接和进一步扩展

时间:2011-02-03 22:47:29

标签: c++ c-preprocessor

我能安全地期待这个

#define TEMPLATE_DECL_BEGIN_0 template <
#define TEMPLATE_DECL_BEGIN_1 TEMPLATE_DECL_BEGIN_0 typename Arg0
#define TEMPLATE_DECL_BEGIN_2 TEMPLATE_DECL_BEGIN_1 , typename Arg1
#define TEMPLATE_DECL_BEGIN_3 TEMPLATE_DECL_BEGIN_2 , typename Arg2
#define TEMPLATE_DECL(N) TEMPLATE_DECL_BEGIN_ ## N >

TEMPLATE_DECL(0)
TEMPLATE_DECL(1)
TEMPLATE_DECL(2)
TEMPLATE_DECL(3)

生成

template < >
template < typename Arg0 >
template < typename Arg0 , typename Arg1 >
template < typename Arg0 , typename Arg1 , typename Arg2 >

在任何合理标准的 C 预处理器上?

我担心的是在上次替换之后连接后的宏扩展:它是否有效,以便在 N 被替换后,例如 2 然后

TEMPLATE_DECL_BEGIN_2

变为

TEMPLATE_DECL_BEGIN_1 , typename Arg1

1 个答案:

答案 0 :(得分:3)

是。从C99标准的6.10.3.3§3开始:

  

对于类似对象和类似函数的宏调用,在替换列表之前   重新检查更多的宏名称来替换,##预处理令牌的每个实例   在替换列表中(不是从参数中)被删除并进行前面的预处理   token与以下预处理标记连接。

和6.10.3.4§3:

  

替换列表中的所有参数都被替换后#and ##   处理已经发生,所有地标预处理令牌都被删除。然后,   重新扫描生成的预处理标记序列以及所有后续标记序列   预处理源文件的标记,以便更换更多的宏名称。

标准保证x ## y在替换更多宏名称之前发生,因此如果您在此时构造宏名称,它将被替换。

这是来自C99标准,但我非常怀疑他们是否从C89标准改变了这个版本,C89标准将是真正适用于C ++的版本。