我应该如何编写我的C ++来为C ++模块做准备?

已经有两个支持C ++模块的编译器:

  • 铿锵: http : //clang.llvm.org/docs/Modules.html
  • MS VS 2015: http : //blogs.msdn.com/b/vcblog/archive/2015/12/03/c-modules-in-vs-2015-update-1.aspx

现在开始一个新的项目时,为了在我的编译器最终发布时能够采用模块特性,我应该注意些什么?

是否可以使用模块,并仍然保持与不支持它的较旧编译器的兼容性?

已经有两个支持C ++模块的编译器

铿锵: http : //clang.llvm.org/docs/Modules.html MS VS 2015: http : //blogs.msdn.com/b/vcblog/archive/2015/12/03/c-modules-in-vs -2015-更新1.aspx

微软的方法似乎是最受关注的方法,主要是因为微软在执行方面投入的资源比目前任何一个铿锵的人都多。 请参阅https://llvm.org/bugs/buglist.cgi?list_id=100798&query_format=advanced&component=Modules&product=clang我的意思是,在C ++模块中有一些大的showstopper错误,而针对C或尤其是Objective C的模块看起来很多在现实世界的代码中更有用。 Visual Studio的最大和最重要的客户,微软,正在努力为模块,因为它解决了大量的内部构build可扩展性问题,微软的内部代码是一些最难的C ++编译任何地方存在,所以你不能扔任何编译器除了MSVC以外(例如,运气好的话可以使用clang或GCC来编译40k行代码)。 因此,Google等使用的clang构build技巧对于微软来说是不可用的,他们有一个巨大的迫切需要,以便尽早修复它。

这并不是说微软的build议在实际应用于大型现实世界的代码库时没有一些严重的devise缺陷。 然而,Gaby认为你应该重构你的代码模块,而我不同意,我可以看到他来自哪里。

现在开始一个新的项目时,为了在我的编译器最终发布时能够采用模块特性,我应该注意些什么?

就目前微软的编译器预计要实现模块而言,你应该确保你的库可以用于所有这些forms:

  1. dynamic库
  2. 静态库
  3. 只有标题库

很多人非常惊讶的是,目前预计要实现的C ++模块保持了这些差异,所以现在你得到了上述三个 C ++模块的变体,第一个看起来像人们期待C ++模块的样子,最后看起来最像一个更有用的预编译头。 您应该支持这些变体的原因是因为您可以重复使用大部分相同的预处理器机制来支持C ++模块,而只需很less的额外工作。

稍后的Visual Studio将允许将模块定义文件(.ifc文件)作为资源链接到DLL中。 这将最终消除MSVC上.lib和.dll区分的需要,您只需将一个DLL提供给编译器,并且它在模块导入时都“正常工作”,不需要任何头文件或其他任何东西。 这听起来有点像COM,但没有COM的大部分好处。

是否可以在单个代码库中使用模块并仍然保持与不支持它的旧版编译器的兼容性?

我会假设你的意思是上面插入的粗体文本。

通常情况下,答案是有更多预处理器macros的乐趣。 #include <someheader>可以变成import someheader内的import someheader ,因为预处理器仍然照常工作。 因此,您可以使用类似下面的代码来标记C ++模块支持的各个库头文件:

 // someheader.hpp #if MODULES_ENABLED # ifndef EXPORTING_MODULE import someheader; // Bring in the precompiled module from the database // Do NOT set NEED_DEFINE so this include exits out doing nothing more # else // We are at the generating the module stage, so mark up the namespace for export # define SOMEHEADER_DECL export # define NEED_DEFINE # endif #else // Modules are not turned on, so declare everything inline as per the old way # define SOMEHEADER_DECL # define NEED_DEFINE #endif #ifdef NEED_DEFINE SOMEHEADER_DECL namespace someheader { // usual classes and decls here } #endif 

现在在你的main.cpp或者其他的东西里,你只需要:

 #include "someheader.hpp" 

…如果编译器有/ experimental:modules / DMODULES_ENABLED,那么你的应用程序会自动使用你的库的C ++ Modules版本。 如果没有,就像我们一直所做的那样,你会得到内联。

我认为这些是对源代码进行尽可能less的更改以使您的代码模块现在就绪。 你会注意到我没有提到构build系统,这是因为我仍然在debugging我编写的cmake工具来让所有这些东西无缝地“工作”,而且我希望在几个月内能够debugging它。 预计明年或者之后的一年,可能会在C ++会议上看到它:)

是否可以使用模块,并仍然保持与不支持它的较旧编译器的兼容性?

不,这是不可能的。 这可能会使用像这样的#ifdef魔术:

 #ifdef CXX17_MODULES ... #else #pragma once, #include "..." etc. #endif 

但这意味着您仍然需要提供.h支持,从而失去所有的好处,而且现在您的代码库看起来相当难看。

如果你想遵循这个方法,检测我刚编写的“ CXX17_MODULES ”最简单的方法就是编译一个小的testing程序,它使用带有你select的构build系统的模块,并且定义一个全局的,编译成功与否。

现在开始一个新的项目时,为了在我的编译器最终发布时能够采用模块特性,我应该注意些什么?

这取决于。 如果你的项目是企业,把盘子上的食物,我会等待几年,一旦它被释放在马厩,以便它被广泛适应。 另一方面,如果你的项目能够承受stream血,那么一定要使用模块。

基本上,Python3和Python2,或者不太相关的PHP7和PHP5都是同样的故事。 你需要find一个良好的最新的程序员,而不是讨厌的人在Debian之间的平衡;-)

Interesting Posts