已经有两个支持C++模块的编译器:
现在开始一个新项目时,为了能够在我的编译器最终发布时采用模块功能,我应该注意什么?
是否可以使用模块并仍然保持与不支持它的旧编译器的兼容性?
模块是#includes的替代品.Clang有一个完整的C++实现.如果我现在想使用Clang使用模块,我该怎么办?
运用
import std.io;
Run Code Online (Sandbox Code Playgroud)
在C++源文件中还没有工作(编译),因为模块的规范(包括语法)不是最终的.
该锵文件指出,经过时-fmodules标志,#包括将被改写到相应的进口.但是,检查预处理器会另外建议(test.cpp只包含#include <stdio.h>一个空的main):
$ clang++-3.5 -fmodules -E test.cpp -o test
$ grep " printf " test
extern int printf (const char *__restrict __format, ...);
Run Code Online (Sandbox Code Playgroud)
此外,使用-fmodulesvs no flags 编译此测试文件会产生相同的目标文件.
我究竟做错了什么?
考虑头文件:
class T
{
private:
int const ID;
public:
explicit T(int const ID_) noexcept : ID(ID_) {}
int GetID() const noexcept { return ID; }
};
Run Code Online (Sandbox Code Playgroud)
或者,或者:
class T
{
private:
int const ID;
public:
explicit T(int const ID_) noexcept;
int GetID() const noexcept;
};
inline T::T(int const ID_) noexcept : ID(ID_) {}
inline int T::GetID() const noexcept { return ID; }
Run Code Online (Sandbox Code Playgroud)
在预模块世界中,这些标头可能会以文本形式包含在多个 TU 中,而不会违反 ODR。此外,由于涉及的成员函数相对较小,编译器可能会“内联”(在使用时避免函数调用)这些函数,甚至优化掉一些实例T。
在最近关于 C++20 完成会议的报告中,我可以阅读以下声明:
我们澄清了
inline模块接口中的含义:意图是未明确声明的函数体不是inline模块 ABI 的一部分,即使这些函数体出现在模块接口中。为了让模块作者更好地控制他们的 …
给定以下模块example
module;
#include "example.h" // `namespace cxx { struct example {}; }`
export module example;
export namespace cxx::containers
{
using cxx::example;
}
Run Code Online (Sandbox Code Playgroud)
cxx::containers::examplecxx::example也可以从我只希望cxx::containers::example出现的地方访问。
import example;
int main()
{
auto v1 = cxx::containers::example();
auto v2 = cxx::example();
}
Run Code Online (Sandbox Code Playgroud)
cxx::example即使我只在命名空间内使用它cxx::containers::example并且#include全局module;片段中的指令应该本地化到它们的模块,但它仍然可见的原因是什么?
我正在阅读有关模块的内容,我希望这样做:
a.cpp
module foo.a;
export namespace foo {
struct A {
void doA();
};
}
import foo.b;
void foo::A::doA() {
B{}.doB();
}
Run Code Online (Sandbox Code Playgroud)
b.cpp
module foo.b;
export namespace foo {
struct B {
void doB();
void start();
};
}
import foo.a;
import std.io;
void foo::B::doB() {
std::cout << "Stuff done!" << std::endl;
}
void foo::B::start() {
A{}.doA();
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中
import foo.b;
int main() {
foo::B{}.start();
}
Run Code Online (Sandbox Code Playgroud)
由于模块接口不能互相使用,为了使其工作,导出的命名空间之后的所有内容都不能成为接口的一部分.根据目前的TS,上述是否正确?对于实现中的循环依赖,是否需要将其拆分为另一个文件?
我在C++模块的上下文中看到了一些对"purview"这个术语的引用,例如在https://gcc.gnu.org/wiki/cxx-modules中:
Baz (); // Baz's declaration visible from purview Quux interface
Run Code Online (Sandbox Code Playgroud)
究竟什么是C++模块权限?
传统上,C++ 库由一个头文件 + 编译成二进制文件(.a, .so, .dylib, .dll, ...)的实现组成。头文件#include在源代码中是d,二进制部分链接到最终的可执行文件。
C++20 的模块会改变这种布局吗?如果是这样,操作系统是否必须升级它们分发核心库的方式,例如 Linux 中的标准库或 Windows 中的其他核心 dll?
我习惯于编写没有模块的代码,其中头文件包含函数声明,如:
// foo.h
class Foo
{
void bar();
};
Run Code Online (Sandbox Code Playgroud)
并且相应的.cpp文件包含以下定义:
// foo.cpp
#include "foo.h"
void Foo::bar()
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这样做是为了减少编译时间并减少依赖性.当使用模块时,这仍然适用吗?将类放在单个文件中的定义与Java和C#的定义方式一样快吗?如果是这种情况,使用模块时是否需要.hpp和.cpp文件?
C++20 标准似乎定义了模块单元的两类:接口/实现单元,以及模块单元是否是分区。这两个分类看起来是正交的:您可以拥有一个是分区的实现单元、一个不是分区的接口单元,等等。
分类的接口/实现轴似乎是关于你能做什么import和不能做什么。但如果这是真的,那么作为命名分区的实现单元有什么意义呢?难道你不能让这个实现单元不是一个分区吗?
这两个概念真的是正交的,还是有些相互依赖的?如果是后者,他们之间的依赖程度如何?