我最近一直在尝试使用 GCC 11 将代码库转换为 C++20 模块。但是,我陷入了以下情况。首先,这是使用标题的方法:
啊
class B;
class A {
public:
void f(B& b);
};
A.cpp
#include "A.h"
#include "B.h"
void A::f(B& b)
{
// do stuff with b
}
(这里Bh的内容不重要)
需要注意的是 B 的前向声明。不是每个使用 A 的人都应该关心 B,所以我使用前向声明来阻止重新编译的发生。使用标头,这种情况非常有效。
问题在于尝试将此代码转换为模块时。主要问题是实体与声明它们的模块相关联,因此在 Ah 中进行前向声明是不可能的。我尝试在全局模块中进行前向声明,但编译器仍然抱怨 B 的定义与其声明位于不同的模块中。我还尝试了第三个模块,它只包含 B 的前向声明,但这仍然是在两个不同的模块中声明和定义 B。所以,我的主要问题是:我怎样才能从模块之外的模块中转发声明一些东西? 我也会对最终产生相同效果的方式感到满意:当 B 更改时,A 的用户不需要重新编译。
在搜索时,我发现一些地方在谈论类似的情况,但由于某种原因它们都不起作用。他们没有工作的原因:
- 有人说有一个带有前向声明的模块。正如我上面所说,这不起作用。
- 有人说要使用宣布的所有权声明。但是,它们已从最终的 C++ 标准中删除。
- 有人说使用模块分区。但是,这仅在 A 和 B 在同一模块中时才有效。A 和 B 不应该在同一个模块中,所以这不起作用。
编辑:作为对评论的回应,以下是我尝试过的一些事情的详细信息:
尝试 1:在 A.mpp 中转发声明 B
A.mpp
export module A;
class B;
export class A {
public:
void f(B& b);
};
B.mpp
export module B;
export class B {};
A.cpp
module A;
import B;
void A::f(B& b)
{
// do stuff with b
}
执行此操作时,gcc 错误
A.cpp:4:11: error: reference to ‘B’ is ambiguous
4 | void A::f(B& b)
| ^
In module B, imported at A.cpp:2:
B.mpp:3:14: note: candidates are: ‘class B@B’
3 | export class B {};
| ^
In module A, imported at A.cpp:1:
A.mpp:3:7: note: ‘class B@A’
3 | class B;
尝试 2:在新模块中前向声明
B_decl.mpp
export module B_decl;
export class B;
A.mpp
export module A;
import B_decl;
export class A {
public:
void f(B& b);
};
B.mpp
export module B;
import B_decl;
class B {};
A.mpp
module A;
import B;
void A::f(B& b)
{
// do stuff with b
}
执行此操作时,gcc 错误
B.mpp:5:14: error: cannot declare ‘class B@B_decl’ in a different module
5 | class B {};
| ^
In module B_decl, imported at B.mpp:3:
B_decl.mpp:3:14: note: declared here
3 | export class B;
尝试 3:在标头中前向声明,在模块中定义
B_decl.h
class B;
A.mpp
module;
#include "B_decl.h"
export module A;
export class A {
public:
void f(B& b);
};
B.mpp
module;
#include "B_decl.h"
export module B;
class B {};
A.cpp
module A;
import B;
void A::f(B& b)
{
// do stuff with b
}
执行此操作时,gcc 错误
B.mpp:7:7: error: cannot declare ‘class B’ in a different module
7 | class B {};
| ^
In file included from B.mpp:3:
B_decl.h:1:7: note: declared here
1 | class B;