C++ 预处理器宏扩展到另一个预处理器指令

C++ 预处理器宏扩展到另一个预处理器指令,c++,macros,c-preprocessor,expansion,preprocessor-directive,C++,Macros,C Preprocessor,Expansion,Preprocessor Directive,起初我以为我需要这个,但最终我避免了。然而,我的好奇心(以及对知识的渴望,哼)让我问: 可以使用预处理器宏,例如 #include "MyClass.h" INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 扩展到另一个include,如 #include "MyClass.h" #include "FooTemplate.h" template class FooTemplate<MyClass>; #包括“MyClass.h” #包括“FooT

起初我以为我需要这个,但最终我避免了。然而,我的好奇心(以及对知识的渴望,哼)让我问:

可以使用预处理器宏,例如

#include "MyClass.h"

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)
扩展到另一个include,如

#include "MyClass.h"

#include "FooTemplate.h"
template class FooTemplate<MyClass>;
#包括“MyClass.h”
#包括“FooTemplate.h”
模板类脚模板;

?

我认为这是不可能的,因为预处理器是单通的。因此它不能发出其他预处理器指令

具体而言,根据C99标准(6.10.3.4第3段):

3.由此产生的结果完全不同 宏替换的预处理令牌 序列未作为 预处理指令,即使它 像一个


有趣的是,这就是为什么c99中添加了一元的
\u Pragma
操作符。因为宏不能发出
#pragma
,但是
#pragma
可以。

C标准对预处理指令(C99-6.10(2)-预处理指令)作了这样的规定:

预处理指令由一系列以开头的预处理标记组成 一个预处理标记(在翻译阶段4开始时)

及(C99-6.10(7)):

预处理指令中的预处理令牌不受宏的约束 扩展,除非另有说明

例如:

#define EMPTY
EMPTY # include <file.h>
因为C标准说明了这一点(C99,6.10.2(4)-源文件包含):

表单的预处理指令

# include pp-tokens new-line
(与前两种形式中的一种不匹配)是允许的。预处理 指令中包含后的标记的处理方式与普通文本中的处理方式相同。(各 当前定义为宏名称的标识符由其替换列表替换 预处理令牌。)


所有预处理器指令都是在宏展开开始之前解释的,因此,不可以将宏展开为#include指令并将其解释为这样。相反,它将被解释为(错误的)C++代码。 当然,它可以发出指令。它不能做的是在同一个预处理器过程中处理它们。因为
##
字符在宏中有特殊的含义,我看不出您如何实际发出指令…实际上GCC预处理器似乎允许“#define X#ifdef X”,其中#ifdef和第二个X之间的空间实际上是换行,当你在上面运行cpp时,它实际上会发出一个#ifdef。其他人可能会对此进行检查,因为我刚刚喝了几杯啤酒:-)是的,似乎可以创建“类似”指令的东西,但标准明确规定(请参见我的编辑)这样的构造不作为指令处理。是的,我并不是说OP可以做他想做的事情。有一天,你会想把你的代码转移到一个操作系统上,比如Linux,在这个操作系统中,case是很重要的(即Foo.h和Foo.h是两个不同的文件),然后所有没有在Windows上发现的拼写错误都会得到解决。或者,如果你是Linux用户,总有一天你会想走另一条路,遇到不同但同样可怕的问题。我这样写是因为我想排除小写转换的问题(类名->文件名)。但这值得一提,谢谢+1.我们的规则是,文件名与类型和函数的命名方案完全匹配。我们和这里的提问者完全一样,类型名FooType将在FooType.h中定义。与任何“风格”指南一样,选择一种风格并坚持下去。话虽如此,我们在linux上进行了大量开发,因此操作系统会自动执行此规则……嗯……好的。那是个错误。我不喜欢在文件名中使用大写字母,但我喜欢在类型名中使用大写字母。但我应该为了这个问题写两个小写字母@Richard Corden:让文件系统和编译器强制执行该规则可能是暂时的,而其他OSs的任何端口都会完全擦除这种安全性。至少,在极权主义的小写文件名规则下,风险行为和错误会在任何问题发生之前立即显现出来。“莫阿拉,我更喜欢它。再想一想,我突然想到,无论您做什么(小写或混合大小写匹配内容),都需要由一些外部实用程序强制执行。总有可能有人会犯错误,除非您有操作系统支持(如我的情况),否则您必须通过一些脚本/工具来检查这一点。检查所有小写字母更容易,但检查名称是否与文件中的至少一个标识符匹配也不难您甚至可以使用一个静态分析工具来完成这项工作!!!;)# include pp-tokens new-line