起初我认为我需要这个,但最终我避免使用它。然而,我的好奇心(和对知识的渴望,嗯)让我问:
例如在代码中,是否可以使用预处理器宏来
#include "MyClass.h"
INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
扩展到另一个包含文件,比如
#include "MyClass.h"
#include "FooTemplate.h"
template class FooTemplate<MyClass>;
?
起初我认为我需要这个,但最终我避免使用它。然而,我的好奇心(和对知识的渴望,嗯)让我问:
例如在代码中,是否可以使用预处理器宏来
#include "MyClass.h"
INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
扩展到另一个包含文件,比如
#include "MyClass.h"
#include "FooTemplate.h"
template class FooTemplate<MyClass>;
?
我相信这是不可能的,因为预处理器是单次遍历的。所以它不能发出其他预处理指令。
具体来说,在C99标准(6.10.3.4第3段)中:
3 结果完全展开的预处理记号序列即使类似于预处理指令也不会被作为预处理指令处理,...
有趣的是,这就是为什么一元运算符_Pragma
被添加到c99中的原因。因为宏无法发出#pragma
,但_Pragma
可以。
#
和##
字符在宏中具有特殊含义,我不认为您实际上可以发出指令... - Evan TeranC标准对预处理指令有如下规定(C99 - 6.10(2) - 预处理指令):
一个预处理指令由一系列预处理标记组成,它以 # 预处理标记开头(在第4个翻译阶段的开始处)...
并且(C99 - 6.10(7)):
预处理指令中的预处理标记不受宏展开的影响,除非另有说明。
EXAMPLE:
#define EMPTY EMPTY # include <file.h>
因为第二行的预处理标记序列在翻译阶段4开始时并不是以#开头的预处理指令,尽管在宏EMPTY被替换后它将成为预处理指令,所以不能将宏扩展到#include预处理指令中。由于宏扩展发生在第4阶段,因此宏不能导致某些东西在第4阶段开始时存在。
但我想指出的是,以下内容可以正常工作:
#ifdef WIN32 #define PLATFORM_HEADER "platform/windows/platform.h" #else #define PLATFORM_HEADER "platform/linux/platform.h" #include PLATFORM_HEADER
因为C标准规定了这一点(C99,6.10.2(4) - 源文件包含):
形式为
# include pp-tokens new-line
(that does not match one of the two previous forms)是允许的。 在指令中包含的预处理标记将像普通文本一样进行处理。
(每个当前定义为宏名称的标识符都将被其预处理标记的替换列表替换。)
所有的预处理指令都会在宏展开之前被解释,因此,不,你不能让一个宏扩展成一个 #include 指令并使其被解释为这样。相反,它将被解释为(错误的)C++代码。