是什么导致编译器在使用包含冒号的类函数宏时出现差异?

What causes this compiler discrepancy whilst using function-like macros containing colons?

A() 宏只会在 MSVC 上展开,而不会在 GCC/Clang 上展开,除非 A() 放置有前缀,例如Test A().

通过 运行 -E (/E) 标志 (godbolt.org) 下的以下代码段:

#define A() HelloWorld::
#define B() ::

A()
B()

我们看到 MSVC 给出了以下输出:

HelloWorld::
::

而GCC/Clang给出了不同的输出:

::

但是 运行 这个片段:

#define A() HelloWorld::

A()
Test A()

为我们提供所有 3 个编译器的以下信息:

HelloWorld::
Test HelloWorld::

为什么 GCC/Clang 输出缺少第一行? 为什么在写入 Test A() 时它会正确展开所有出现的地方? 这是在标准中明确定义的,还是特定于编译器的?

这是 Compiler Explorer (godbolt.org) 默认情况下如何呈现输出的产物。禁用输出窗格中的 .LX0 选项,它将显示您期望的输出。

Compiler Explorer 假定输出是程序集,并将 HelloWorld:: 视为未使用的标签,由 .LX0 选项删除。

在你的第二个例子中 HelloWorld:: 没有被删除,因为它稍后出现在输出中使得它看起来好像使用了 "label" 并且因为 .LX0 只过滤标签未使用,它不会删除它。

MSVC 不会发生这种情况,因为 MSVC 的 /E 输出未显示在程序集窗格中。

一般来说,如果您想查看完整的未经过滤的编译器输出,请取消选中汇编窗格中的所有框。 (我不知道是否还有其他无法禁用的处理正在发生。)

另请参阅 this Compiler Explorer issue-E 选项的显示问题有关。