Модули C++ пересылают объявление сущности из другого модуляC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Модули C++ пересылают объявление сущности из другого модуля

Сообщение Anonymous »

Недавно я пытался преобразовать кодовую базу в модули C++20 с помощью GCC 11. Однако я застрял в следующей ситуации. Во-первых, вот как это было сделано с помощью заголовков:
А.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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»