我最近一直在尝试使用 GCC 11 将代码库转换为 C++20 模块。但是,我遇到了以下情况。首先,这是使用标头完成的方法:
\n啊
\nclass B;\n\nclass A {\n public:\n void f(B& b);\n};\nRun Code Online (Sandbox Code Playgroud)\na.cpp
\n#include "A.h"\n#include "B.h"\n\nvoid A::f(B& b)\n{\n // do stuff with b\n}\nRun Code Online (Sandbox Code Playgroud)\n(Bh的内容在这里并不重要)
\n需要注意的是 B 的前向声明。并不是每个使用 A 的人都应该关心 B,所以我使用前向声明来阻止重新编译的发生。有了标题,这种情况就完美了。
\n问题在于尝试将此代码转换为模块时。主要问题是实体与声明它们的模块相关联,因此在 Ah 中向前声明是不可能的。我尝试在全局模块中进行前向声明,但编译器仍然抱怨 B 的定义与其声明位于不同的模块中。我还尝试使用第三个模块,其中仅包含 B 的前向声明,但这仍然是在两个不同的模块中声明和定义 B。所以,我的主要问题是:如何从模块外部转发声明某些内容? 我也会对最终产生相同效果的方式感到满意:当 B 更改时,A 的用户不需要重新编译。
\n在搜索时,我发现了一些地方谈论类似的情况,但由于某种原因它们都不起作用。他们不起作用的原因:
\n编辑:为了回应评论,以下是我尝试过的一些事情的详细信息:
\n尝试 1:在 A.mpp 中转发声明 …
我最近一直在试验 MSVC 提供的模块实现,我遇到了一个有趣的场景。我有两个在它们的接口中相互依赖的类,这意味着我必须使用前向声明来编译它。以下代码显示了一个示例:
Module interface
export module FooBar;
export namespace FooBar {
class Bar;
class Foo {
public:
Bar createBar();
};
class Bar {
public:
Foo createFoo();
};
}
Run Code Online (Sandbox Code Playgroud)
Module implementation
module FooBar;
namespace FooBar {
Bar Foo::createBar() {
return Bar();
}
Foo Bar::createFoo() {
return Foo();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想将这两个类拆分为它们自己的名为Foo和的模块Bar。但是,每个模块都需要导入另一个模块,因为它们的接口相互依赖。根据目前的模块提案,不允许循环接口导入。这篇文章建议使用proclaimed ownership声明,但是在模块的MSVC实现中似乎还没有实现。
因此,我是否正确假设目前无法使用 MSVC 提供的当前实现解决这种情况?还是我缺少一些替代方案?在这种情况下,情况非常简单,但是我在模块化具有许多具有此类依赖关系的类的库时遇到了这个问题。我意识到循环依赖通常表明设计不佳,但在某些情况下,它们不可避免或难以重构。