Я уже несколько дней бьюсь над этой проблемой, прочитал много документации и постов о новых модулях C ++ 20, среди которых этот официальный , этот и это еще один в Stackoverflow , но я действительно не могу решить эту проблему.
Я использую компилятор MSV C, поставляемый с Visual Studio Preview 16.6.0 2.0 . Я знаю, что это еще не стабильный выпуск, но я бы хотел поиграться с новыми функциями, чтобы начать их изучение.
В основном я написал модуль (myModule
) и 2 раздела этого модуля (mySubmodule1
и mySubmodule2
), и я реализовал их в двух файлах реализации модуля (mySubmodule1Impl.cpp
и mySubmodule2Impl.cpp
).
mySubmodule1
зависит от mySubmodule2
и наоборот. Вот источник:
mySubmodule1.ixx
export module myModule:mySubmodule1;
export namespace myNamespace{
class MyClass2;
class MyClass1{
public:
int foo(MyClass2& c);
int x = 9;
};
}
mySubmodule2.ixx
export module myModule:mySubmodule2;
import :mySubmodule1;
export namespace myNamespace{
class MyClass2 {
public:
MyClass2(MyClass1 x);
int x = 14;
MyClass1 c;
};
}
mySubmodule1Impl. cpp
module myModule:mySubmodule1;
import :mySubmodule2;
int myNamespace::MyClass1::foo(myNamespace::MyClass2& c) {
this->x = c.x-14;
return x;
}
mySubmodule2Impl. cpp
module myModule:mySubmodule2;
import :mySubmodule1;
myNamespace::MyClass2::MyClass2(myNamespace::MyClass1 c) {
this->x = c.x + 419;
}
myModule.ixx
export module myModule;
export import :mySubmodule1;
export import :mySubmodule2;
Как видите, я могу переслать объявление MyClass2
в mySubmodule1
, но я не могу переслать объявление MyClass1
в mySubmodule2
, потому что в MyClass2
я использую конкретный объект типа MyClass1
.
Я компилирую с этой строкой: cl /EHsc /experimental:module /std:c++latest mySubmodule1.ixx mySubmodule2.ixx myModule.ixx mySubmodule1Impl.cpp mySubmodule2Impl.cpp Source.cpp
, где Source.cpp
является просто основным.
Я получаю печально известную ошибку C2027: использование неопределенного типа 'myNamespace :: MyClass2' в mySubmodule1Impl.cpp
и mySubmodule2Impl.cpp
в строках, где я использую MyClass2
. Более того, компилятор говорит мне взглянуть на объявление MyClass2
в mySubmodule1.ixx
, где есть предварительное объявление.
Теперь я действительно не понимаю, где моя ошибка. Я проверял снова и снова, но логика c программы кажется мне идеальной. Порядок компиляции файлов должен определять MyClass2
до того, как он будет использован в реализации!
Я пытался скомпилировать эту точную программу, используя "старые" файлы .h и. cpp вместо модулей. и он компилируется и работает нормально. Поэтому я предполагаю, что что-то упустил в отношении этих новых модулей.
Я проверил первое официальное предложение модулей (параграф 10.7.5) , и в первом была конструкция названная провозглашенная декларация о собственности , которая в таких случаях казалась идеальной. В основном это позволяет вам импортировать объект, принадлежащий другому модулю в текущем модуле, но без импорта самого модуля. Но в более поздних версиях предложения никаких признаков этого нет. Абсолютно ничего. А в разделе «changelog» нового предложения оно даже не цитируется.
Пожалуйста, не говорите, что циклические c зависимости плохие. Я часто знаю, что они плохие, но не всегда. И даже если вы думаете, что они всегда плохие, я не прошу большого пальца. Я спрашиваю, почему мой код компилируется со «старым» .h +. cpp, но не с новыми модулями. Почему компоновщик не видит определение MyClass2
.
EDIT 1
Вот новый дизайн, предложенный в ответе, но он все еще не работает. Я получаю точно такие же ошибки:
mySubmodule1Impl. cpp
module myModule;
int myNamespace::MyClass1::foo(myNamespace::MyClass2& c) {
this->x = c.x-14;
return x;
}
mySubmodule2Impl. cpp
module myModule;
myNamespace::MyClass2::MyClass2(myNamespace::MyClass1 c) {
this->x = c.x + 419;
}
Все остальные файлы не изменены.