C++ Modules conformance improvements with MSVC in Visual Studio 2019 16.5

栏目: IT技术 · 发布时间: 4年前

内容简介:January 22nd, 2020C++20 is right around the corner. Along with the new standard comes the much anticipated Modules feature! The compiler teaminitially announced that we were working on the Modules TS back in 2017 and since then we have been hard at work im

Cameron

January 22nd, 2020

C++20 is right around the corner. Along with the new standard comes the much anticipated Modules feature! The compiler teaminitially announced that we were working on the Modules TS back in 2017 and since then we have been hard at work improving the feature and improving compiler conformance around this feature. We finally feel it is time to share some of the progress we have made on the conformance front for Modules.

What’s new?

  • are a new form of translation unit which act like portable PCHs.
  • Context sensitive module and import keywords provide users with more flexibility when using these terms as identifiers in code.
  • Global module fragmentis a way of separating non-modular code from module interface code when composing a module interface.
  • are a type of module interface which compose a larger module interface.

Header Unit Support

In C++20 [module.import]/5 describes the import of a new translation unit type, the header unit. The semantics of this type of import are further elaborated on in [module.import]/5 and one of the more important pieces of information is that macros defined in that imported header are also imported:

myheader.h

#pragma once
 
#include <cstdio>
 
#define THE_ANSWER 42
#define STRINGIFY(a) #a
#define GLUE(a, b) a ## b

main.cpp

import "myheader.h";
 
int f() { return THE_ANSWER; }
 
int main() {
  const char* GLUE(hello_,world) = STRINGIFY(Hello world);
  std::printf("%s\n", hello_world);
}

The sample above can be compiled using the new /module:exportHeader switch:

$ cl /std:c++latest /W4 /experimental:module /module:exportHeader myheader.h /Fomyheader.h.obj
 $ cl /std:c++latest /W4 /experimental:module /module:reference myheader.h:myheader.h.ifc main.cpp myheader.h.obj

Notice the use of /module:exportHeader , the argument to this option is a path (relative or absolute) to some header file. The output of /module:exportHeader is of our .ifc format. Meanwhile, on the import side, the option /module:reference has a new argument form which is <path-to-header>:<path-to-ifc> and either one or both of the paths expressed in the argument to /module:reference can be relative or absolute. It is also important to point out that without the /Fo switch the compiler will not generate an object file automatically, the compiler will only generate the .ifc.

One other intended use case of the /module:exportHeader is for users (or build systems) to provide a text argument to it which represents some header name as the compiler would see. A quick example is:

$ cl /std:c++latest /EHsc /experimental:module /module:exportHeader "<vector>" /module:showResolvedHeader
 <vector>
 Note: resolved <vector> to 'C:\<path-to-vector>\inc\vector'

This use of /module:exportHeader enables the compiler to build header units using the header search mechanism as if the argument were written in source. This functionality also comes with a helper switch, /module:showResolvedHeader , to emit the absolute path to the header file found through lookup.

Note to readers: there is a known limitation with /module:exportHeader and its interaction with /experimental:preprocessor these two switches are currently incompatible and will be resolved in a future release.

Context Sensitive module and import keywords

In the Modules TS both module and import were treated as keywords. It has since been realized that both of these terms are commonly used as identifiers for user code and hence a number of proposals were accepted into C++20 which add more restrictions as to when module and import are keywords. One such proposal was P1703R1 which adds context sensitivity to the import identifier. Another such proposal—but one which is not yet accepted—is P1857R1 . P1857R1 is interesting in that it is the most restrictive paper in defining when module and import are keywords or identifiers.

As of 16.5 MSVC will implement both P1703R1 and P1857R1. The result of implementing the rules outlined in these two papers is that code such as:

#define MODULE module
#define IMPORT import
 
export MODULE m;
IMPORT :partition;
IMPORT <vector>;

Is no longer valid and the compiler will treat the macro expansion of both MODULE and IMPORT as identifiers, not keywords. For more cases like this please see the papers, in particular P1857R1 provides some useful comparison tables describing the scenarios affected by the change.

Global Module Fragment

Since the merging of Modules into C++20 there was another new concept introduced known as the global module fragment. The global module fragment is only used to compose module interfaces and the semantics of this area borrows semantics described in the Modules TS regarding entities attached to the global module. The purpose of the global module fragment is to serve as a space for users to put preprocessor directives like #include ‘s so that the module interface can compile, but the code in the global module fragment is not owned by or exported directly by the module interface. A quick example:

module;
#include <string>
#include <vector>
export module m;
 
export
std::vector<std::string> f();

In this code sample the user wishes to use both vector and string but does not want to export them, they are simply an implementation detail of the function they wish to export, f . The global module fragment in particular is the region of code between the module; and export module m; . In this region the only code which can be written are preprocessor directives; #if and #define are fair game. It is important to note that if the first two tokens of the translation unit are not module; the interface unit is treated as though a global module fragment does not exist and this behavior is enforced through [cpp.global.frag]/1 .

Module Partitions

Module partitions provide users with a new way of composing module interface units and organizing code of a module. At their very core, module partitions are pieces of a larger module interface unit and do not stand on their own as an interface to import outside of the module unit. Here is a quick example of a simple module interface which uses partitions:

m-part.ixx

export module m:part;
 
export
struct S { };

m.ixx

export module m;
export import :part;
 
export
S f() { return { }; }

main.cpp

import m; // 'm' is also composed of partition ':part'.
 
int main() {
  f();
}

To compile the sample:

cl /experimental:module /std:c++latest /c m-part.ixx
 cl /experimental:module /std:c++latest /c m.ixx
 cl /experimental:module /std:c++latest main.cpp m.obj

Notice that we did not explicitly add /module:reference to any invocation of the compiler, this is because we have introduced a naming scheme for module partitions which ease the use of the feature—just like we have for normal module interface units where the filename represents the module name directly. The pattern that module partitions use is <primary-module-name>-<module-partition-name> . If your module partitions follow that pattern the compiler can automatically find interface units for partitions. Of course, should you actually want to specify the module interfaces on the command line simply add the appropriate module:reference arguments.

The standard refers to partitions in general as being interface units [module.unit]/3 , however there is one exception and that is what we refer to as an “internal” partition. These internal partitions are not interfaces and only serve to facilitate the implementation details of a module unit. It is expressly ill-formed to export an internal partition (see translation unit 3 in section 4 of [module.unit]). MSVC implements the creation of internal partitions through a new switch /module:internalPartition . An example of using an internal partition:

m-internals.cpp note the .cpp extension

module m:internals;
 
void g() { } // No declaration can have 'export' in an internal partition.

m.ixx

export module m;
import :internals; // Cannot export this partition.
 
export
void f() { g(); }

To compile this interface:

cl /experimental:module /std:c++latest /module:internalPartition /c m-internals.cpp
 cl /experimental:module /std:c++latest /c m.ixx

As previously mentioned, the :internals partition can only be used to implement parts of the module interface m and cannot contribute to it directly.

Closing Thoughts

C++20 is bringing a lot of new concepts (literally and figuratively) to C++ and Modules are one of the largest contributors to how we will write code differently in the future. These MSVC conformance changes will help users facilitate the transition into thinking about how we organize and reason about interfaces to our APIs. As with all of our preview features the switches and compiler behavior with respect to modules are subject to change once we are ready to declare the toolset C++20 complete.

We urge you to go out and try using MSVC with Modules. 16.5 is available right now in preview through the Visual Studio 2019 downloads page!

As always, we welcome your feedback. Feel free to send any comments through e-mail at visualcpp@microsoft.com or through Twitter @visualc . Also, feel free to follow me on Twitter @starfreakclone .

If you encounter other problems with MSVC in VS 2019 please let us know via theReport a Problem option, either from the installer or the Visual Studio IDE itself. For suggestions or bug reports, let us know through DevComm.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Growth Hack 這樣做

Growth Hack 這樣做

Xdite / PCuSER電腦人文化 / 2016-5-7 / 300.00台幣

◎具體教你在預算有限的情況之下,把成長做出來的可行與必要方法! ◎帶動台灣成長駭客話題的專業講師,親授讓產品突破80分的成長秘笈 @這本書要給誰看? 1. 創業者、個人品牌經營者,想要提高自己服務轉換率的人。 2. 空有產品,但是賣不出去,花了錢投廣告卻效果低落的人。 @這本書有什麼不一樣? 1.全球最重要的趨勢,台灣最知名的 Growth Hack 講師 Xd......一起来看看 《Growth Hack 這樣做》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具