面对是否有可能在预处理器中选择#include
的问题,我立即认为不可能。
..后来发现它确实是可能的,你只需要注意参数扩展(例如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>
更新: 参考 C 标准,澄清问题。
答案 0 :(得分:7)
来自C ++ 2003草案的§16.2-4(“源文件包含”):
C99的第6.10.2-4段说的是相同的。表单
的预处理指令允许使用# include pp-tokens new-line
(与前两种形式中的一种不匹配)。指令中
include
之后的预处理标记的处理方式与普通文本一样(当前定义为宏名称的每个标识符都替换为其预处理标记的替换列表)。
上面提到的“前两个表单”是# 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
进行宏扩展,宏函数的参数和替换时宏函数的主体。我认为这就是一切。
答案 1 :(得分:2)
这是C预处理器的一个非常基本的功能 - 例如,#ifdef
等指令在与可能是宏的参数(如果有的话)一起使用时,除了之外没有任何意义要知道论证不允许是一个宏,#ifdef
可能的目的是什么?!)。
我不确定ISO C标准的章节和经文是如何帮助你的 - 我记得C ++标准并没有改变预处理器的操作。