А.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: Переслать объявление B в A.mpp
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;
Подробнее здесь: https://stackoverflow.com/questions/679 ... her-module
Мобильная версия