官宣 我们非常高兴地宣布,从Visual Studio 2019 v16.6 Preview 2版本开始,MSVC工具集中的标准化预处理器(Conformant Preprocessor)将得到全面的支持。 2018年那会,我们在一篇文章里专门介绍了关于处理器的一些重大更改。从那个时候开始,我们走了很长一段路了,这条路上真是充满了艰险。今天,针对C/C++的标准化预处理器终于开发完成了,并且我们将这一特性从实验版本中移出,开发者可以通过编译开关[/Zc:preprocessor]开关里启用这项特性。除了符合标准之外,预处理器还将支持C++ 20里的[__VA_OPT__],同时也可以在C语言模式下使用。 有哪些更新? 为了符合标准,我们向现有的预处理器和MSVC编译器添加了若干个附加功能,其中包括各种错误修复,以及对__ VA_OPT__和_Pragma的支持。错误修复涉及到了预处理器的各个部分,从参数扩展(parameter expansion)和特殊的宏名称(如__FUNCSIG__)到参数错误报告和行号修复。特别感谢Edward Diener提供了许多宝贵的意见。 __VA_OPT__ __VA_OPT__是C++20中可变参数宏的一项新功能。它允许您根据是否使用附加参数调用可变参数宏来选择插入标记。下面是一个使用了标准化的逗号分隔的例子: _Pragma _Pragma运算符是预处理器中的长期缺陷之一,并且它阻碍了MSVC符合C++和C99标准的步伐。尽管MSVC具有非标准化的__pragma关键字,但是它们语义上的差异在于:_Pragma将字符串文字作为其参数而不是一系列预处理器标记。现在,幸运的是,这项特性也已经实现了。 其他的更新 除了上面的两项更新,新版本中还有一些和模块有关的关键字变化,这些变化将使得C++ 20中的模块变得可用。另外,通过[/E]和[/P]选项启用的[仅预处理器输出]现在显得更加简化清晰了,原因是它减少了很多行指令的数量并修复了一些格式方面的问题。 如何在你的环境中启用标准化的预处理器 你只需要在编译开关中添加一个额外的[/Zc:preprocessor]开关,就可以使用标准化的预处理器了。这个编译开关在C和C++语言模式下都是可用的。尽管它适用于任何语言级别,但是我们计划在将来的版本中为[/std:c++latest]启用它。 通过测试宏[_MSVC_TRADITIONAL]是否定义且其值为0,可以来检测标准化预处理器在当前环境中是否可用,如下图所示: 旧式的预处理器仍被支持,它将继续充当遗留代码的兼容层,但它的存在只是为了能使遗留代码能正常通过编译和运行。此外,编译开关[/experimental:preprocessor]也仍然可用,只是它将在VS2019 v16.6版中升级为新的编译开关[/Zc:preprocessor]。在以后的VS版本中,它将被删除。如果你的项目已经用到了这个实验性的开关的话,请尽快迁移到新的编译开关版本。 接下来 我们目前正在改进诊断组件,这将为宏调用和宏编译错误提供更好的扩展上下文信息。当前没有任何其他编译开关隐含此功能,但是一旦我们稳定了公共SDK头文件中那些容易使用非标准化的宏之后,我们就会将它包含在[/std:c++latest]中。 所以还是建议大家使用最新版本的Windows SDK,因为更高版本的SDK中修复了许多烦人的警告。 总结 大清可能真的亡了,连万年不变的预处理都变了,下次写代码的时候,可得注意了。 人,毕竟还是要与时俱进一下。