预处理:定义 “import” 的缩写是否合法?

4
为解决一个代码挑战,我想要尽可能缩小代码量。我有一个把 "import" 定义为速记符号的想法:
#define I import
I<vector>;

简短的Godbolt示例

当然,这里的意图是重复利用I来实际节省字节。

C++20中是否合法?

思考/目前我所了解到的:

  • 根据cppreference的说法,“模块和导入指令也是预处理指令”。因此,我认为问题归结为我们是否保证预处理器首先将I替换为我们定义的内容?
  • 我认为,处理import指令应该在第4个翻译阶段进行,在整个阶段中,除非另有规定,否则I不应进行宏扩展([cpp.pre]-7)。对于这种情况,是否有规定要另作说明?
  • 这种方法是否可能作为预处理器重新扫描的一部分工作?
  • Godbolt上的Clang和GCC无法编译,但据我所知,它们尚未支持导入标准库头文件而不需要额外步骤,并且使用简写版本时给出相同的错误信息,这表明它可能有效(?)。
  • 相同的方法,但使用include而不是import,无法在gcc和clang中工作,因此可能不合法。

1
你为什么在代码高尔夫挑战中考虑合法性? - MikeCAT
1
我认为这个链接是你要找的。 - NathanOliver
1
无论如何都不会起作用,预处理器只是转换文本,它不能创建新的预处理器指令,这就是你试图做的事情。 - Aconcagua
@NathanOliver 谢谢你提供的链接。我可能有误解,但我认为这排除了相反的情况,即它说 #define import X 然后跟着 import <vector>; 将是不合法的。 - He3lixxx
@Aconcagua:对我来说,看起来我发布的内容在Godbolt上使用GCC和clang会起作用——使用#define I import,它们会给出与仅使用import <vector>相同的错误。 - He3lixxx
显示剩余2条评论
1个回答

11

否。

[cpp.pre]/1:

预处理指令由一系列满足以下限制的预处理记号组成:在第4阶段开始时,序列中的第一个记号称为“引导指令记号”,以源文件中的第一个字符开头(可选地跟在不含换行符的空白后面)或跟随至少包含一个换行符的空白。它是……

预处理指令性在任何宏替换之前,在翻译阶段4的开始时确定。因此,I<vector>; 不被认为是一个指令,而I 的宏展开中的import也不会被“import-keyword”记号取代。 这反过来意味着它在翻译阶段7时不会被识别为“模块导入声明”,而只是一次试图在没有前置声明的情况下使用标识符import的非法尝试。

这个过程的目的是确保构建系统可以在不必完全预处理文件的情况下了解文件的依赖关系,如果导入是通过宏替换形成的,则需要进行完全预处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接