【发布时间】:2021-08-29 07:05:45
【问题描述】:
我最近一直在尝试使用 GCC 11 将代码库转换为 C++20 模块。但是,我遇到了以下情况。首先,这是使用标题的方法:
啊.h
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
}
(这里B.h的内容不重要)
需要注意的是 B 的前向声明。不是每个使用 A 的人都应该关心 B,所以我使用前向声明来阻止重新编译的发生。有了标头,这种情况就完美了。
问题在于尝试将此代码转换为模块时。主要问题是实体与声明它们的模块相关联,因此在 A.h 中进行前向声明是不可能的。我尝试在全局模块中进行前向声明,但编译器仍然抱怨 B 的定义与其声明位于不同的模块中。我还尝试了第三个模块,它只包含 B 的前向声明,但这仍然是在两个不同的模块中声明和定义 B。所以,我的主要问题是:我怎样才能从模块之外的模块中转发声明一些东西?我也会对最终产生相同效果的方式感到满意:A 的用户不会B改变时需要重新编译。
在搜索时,我发现了一些地方在谈论类似的情况,但由于某种原因它们都不起作用。他们没有工作的原因:
- 有人说有一个带有前向声明的模块。正如我上面所说,这不起作用。
- 有人说要使用声明的所有权声明。但是,它们已从最终的 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;
【问题讨论】:
-
"但这仍然是在两个不同的模块中声明和定义 B" 你怎么知道的?你遇到了什么错误?另外,您能否向我们展示您尝试过的所有模块案例的代码?您是否为这些声明使用了模块分区?
-
我正要开始测试从头文件到模块的转换,但这是一个主要的阻碍。几乎所有我想要分离的东西都具有需要前向声明的依赖关系。
标签: c++ c++20 forward-declaration c++-modules gcc11