2009-11-15 35 views
3

面对在预处理器中是否可以选择#include s的问题,我立即认为不可能
..后来才发现它确实可行,你只需要注意参数扩展(例如Boost.Preprocessor可以处理)。宏作为预处理器指令的参数

尽管如果可能的话,我会避免实际做到这一点,但我想知道为什么这会起作用。目前,我未能在C++或C标准中得到有用的理解。
参数化宏是否允许用于任何预处理器指令? (除了#define/#undef
有人可以参考这是允许和总结吗?

为好奇利用Boost.Preprocessor为了简单

实施例:

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/stringize.hpp> 

#define INC_LOCAL(a,b) BOOST_PP_STRINGIZE(BOOST_PP_CAT(BOOST_PP_CAT(a,b),.h)) 
#define INC_GLOBAL(a,b) BOOST_PP_CAT(BOOST_PP_CAT(<,a),BOOST_PP_CAT(b,>)) 

#include INC_LOCAL(loc,al) // #include "local.h" 
#include INC_GLOBAL(vect,or) // #include <vector> 

更新: 引用Ç标准,澄清问题。

回答

7

从§16.2-4( “源文件包含”)的C++ 2003年选秀:

形式的预处理指令

# include pp-tokens new-line 

(不匹配前两次的一个表格)是允许的。指令中的include之后的预处理标记将按照正常文本(当前定义为宏名称的每个标识符都被替换为预处理标记的列表)处理。

C99的6.10.2-4说的是一样的。

上面提到的“两种以前的形式”是# include <h-char-sequence># include "q-char-sequence"。该部分似乎过于简单,无法总结。

对于其他指令,在任何identifier预处理标记不进行宏扩展(注意不是由语法定义的这种行为,但通过C++§16/C§6.10):

# if constant-expression new-line [group] 
# ifdef identifier new-line [group] 
# ifndef identifier new-line [group] 
# elif constant-expression new-line [group] 
# else new-line [group] 
# endif new-line 
# include pp-tokens new-line 
# define identifier replacement-list new-line 
# define identifier lparen [identifier-list]) replacement-list new-line 
# undef identifier new-line 
# line pp-tokens new-line 
# error [pp-tokens] new-line 
# pragma [pp-tokens] new-line 
# new-line 

#line是通过C++§16.4-5/C§6.10.4-5进行了明确的宏观扩展。没有提到#error(C++§16.5/C§6.10.5)和#pragma(C++§16.6/C§6.10.6)的扩展。 C++§16.3-7/C 6.10。3-8州:

如果#预处理令牌后面跟着一个标识符,在预处理指令可以开始的位置以词汇形式出现,则标识符不受宏替换的限制。

C++§16.3.1/C§6.10.3.1-1告诉我们,当所述参数给宏函数代入replacement-list,他们是第一宏扩展。类似地,C++第16.3.4节/C第6.10.3.4节中,预处理器宏在替换之后展开replacement-list

总之,宏扩展是针对#if,#elif,#include,#line,宏函数的参数和被替换的宏函数的主体完成的。我认为这就是一切。

+0

好吧,'pp-tokens'让我进入'preprocessing-token',从那里只有'preprocessing-op-or-punc'看起来不错,但只给一些操作员。 – 2009-11-15 05:50:46

+0

所以'像普通文本一样处理'意味着像'identifier(identifier,...)'这样的宏扩展。 – 2009-11-15 06:17:00

+0

当然。结果可能有未定义的行为。 – outis 2009-11-15 06:31:43

2

这是C预处理器的一个非常基本的功能 - 例如,与这是有可能的宏(如果你必须知道的是,争论是不允许的参数使用时,一个指令,如#ifdef使得零感除了作为宏,#ifdef可能的目的是?!)。我不确定ISO C标准的章节和章节会如何帮助你 - 我记得,C++标准不会改变预处理器的操作。

+0

更正:我现在感到困惑其他参数化宏只允许在任何pp-指令,并希望澄清。 – 2009-11-15 05:28:15