VS2019v165新特性出炉增强对C

宣告

C++20标准马上就要来了。伴随着新标准的发布,我们一直期待的Modules特性终于粉墨登场了。早在年,编译器开发团队就写了一篇文章表明他们正在围绕着ModulesTS开展了工作,从那个时候开始,我们就一直努力的工作来改进这一特性并提升编译器对这一标准特性的适应性。今天,我们终于觉得是时候来分享一些我们在Modules支持上的一些进展了。

有哪些新东西?

HeaderUnits:是一种新的翻译单元(TranslationUnit)形式,可以将它看作是一个可移植的PCH。新增上下文可感知的关键字module和import:用于在代码中使用这些标识符时提升足够的灵活性。Globalmodulefragment:当组合一个模块的接口时,这是一种从模块接口代码中分离出非模块代码的新方式。ModulePartitions:一种模块接口的类型,用来组合一个大型模块接口。HeaderUnits支持

在C++20[module.import]/5中描述了一种新的翻译单元的引入,这个新的翻译单元就是所谓的HeaderUnit。有关它的具体语义已经在[module.import]/5中做出了详细的解释。其中最为重要的一点是:在被导出的头文件中,定义在其中的宏也会被同样的导出。我们举个例子如下:

myheader.h

myheader.cpp

以上代码可以使用新的编译开关/module:exportHeader进行编译,如下所示:

请注意这里对/module:exportHeader编译开关的使用,它的输入参数是一个头文件的路径(相对路径或绝对路径)。/module:exportHeader的输出是我们内部定义的.ifc格式的文件。同时,在导入端,我们使用了/module:reference编译开关,它的参数是:,它们中的任何一个都可以是相对路径或绝对路径。另外一个重要的地方是:如果没有指定/Fo选项,则编译器将不会自动生成object文件,它智慧生成.ifc文件。

/module:exportHeader的另一个使用场景是用于向用户或构建系统提供一个文本参数,这个文本参数将会作为某些头文件的名字被编译器所看见。下面是一个例子:

在上面的例子中,我们使用了/module:exportHeader来提示编译器:编译HeaderUnits时使用头文件的搜索顺序,就像这个参数被写到源文件中一样。我们为这个功能也单独提供了一个开关:/module:showResolvedHeader,这个开关将会在查找阶段输出被找到的头文件的绝对路径。

请注意:目前还不能同时使用/module:exportHeader和/experimental:preprocessor这两个编译开关,因为它们是不兼容的。在将来的版本中,这个问题将会得到解决。

上下文可感知的关键字module和import

在ModulesTS中,module和import是两个新的关键字。但是长久以来,我们观察到这两个名词被大量的用在了用户代码中,因此在C++20中,有大量的关于这两个关键字相关的提议。例如,RR1就是这样一项提议,在这个提议中添加了对import关键字的上下文可感知性。另一项类似的提议是PR1(该提议还未被采纳)。从目前看来,PR1是将module和import作为关键字的最为严格的提议。从VSv16.5开始,MSVC将实现PR1和PR1这两个提议。下面是一个例子:

在上面的代码中,MODULE和IMPORT将被视为标识符,而不是关键字。在相关的报告中我们将会看到更多类似的案例,特别是在PR1中,提供了一些有用的对比表格来描述此变更所带来的影响。

Globalmodulefragment

除了modules被引入到C++20之外,还有另外一项新的特性被引入,那就是所谓的”globalmodulefragment”。globalmodulefragment只会在组合模块接口的情况下被使用,它的语义借用了ModuleTS中有关挂接到GlobalModule的实体的概念。globalmodulefragment的目的是用来作为预处理指令例如#include的一个空间。因此,模块接口可以被编译,但是在globalmodulefragment中的代码却不被模块接口所拥有或者直接导出。以下是一个例子:

在以上的代码中,用户希望使用vector和string但是不希望导出它们,它们只是导出函数f的实现细节。globalmodulefragment是位于module;和exportmodulem;之间的一个代码区域。只有类似于#if和#define这样的预处理语句才可以被写入到这片代码区域中。需要特别注意的是,前两个定义的token不能看作是module。接口单元被看作是一个globalmodulefragment,这一特性通过[cpp.global.frag]/1被强制执行。

ModulePartitions

ModulePartitions为用户提供了一种新的组合模块接口单元和组织模块代码的方式。在核心层面,ModulePartitions是一些大型模块接口单元的组成部分,它们并不作为接口用于外部模块单元的导入。下面的例子中,我们定义了一个简单的模块接口,它使用到了两个Partitions。

为了编译上面的例子代码,可以使用如下的编译指令:

之前提到过的,上述代码中的:internalspartition只能被用在模块接口m的实现部分,而不能被直接使用。

总结

C++20为C++世界带来许多新的概念,其中最大的贡献就是Modules,它彻底改变了我们编写代码的方式。MSVC将会帮助用户重新认识我们组织API的方式以及背后的一些思想。当我们准备宣布C++20实现全部完成之时,上文中提到的所有编译开关和有关模块的编译器行为都有可能会改变。




转载请注明:http://www.aierlanlan.com/rzfs/1365.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了