私はこの問題に何日も頭を悩ませてきました.新しいC ++ 20モジュールに関する多くのドキュメントと投稿を読みました.その中には、この公式のもの、これ、およびこれがStackoverflowにありますが、私は本当にこの問題を解決できません.
Visual Studio Preview 16.6.0 2.0で提供される MSVC コンパイラを使用しています。まだ安定したリリースではないことはわかっていますが、新しい機能をいじって学習を開始したいと思っています。
基本的に、モジュール ( myModule
) とこのモジュールの 2 つのパーティション (mySubmodule1
およびmySubmodule2
) を作成し、それらを 2 つのモジュール実装ファイル (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;
ご覧のとおり、 in を前方宣言できますがMyClass2
、 inmySubmodule1
を前方宣言することはできません。これは、 MyClass1
inでタイプ の具象オブジェクトを使用しているmySubmodule2
ためです。MyClass2
MyClass1
私はこの行でコンパイルします: cl /EHsc /experimental:module /std:c++latest mySubmodule1.ixx mySubmodule2.ixx myModule.ixx mySubmodule1Impl.cpp mySubmodule2Impl.cpp Source.cpp
where Source.cpp
is just the main.
悪名高いエラー C2027: use of undefined type 'myNamespace::MyClass2' in mySubmodule1Impl.cpp
and mySubmodule2Impl.cpp
at the lines where I use が表示されますMyClass2
。さらに、コンパイラは、前方宣言があるMyClass2
inの宣言を確認するように指示します。mySubmodule1.ixx
さて、どこが間違っているのか本当にわかりません。何度もチェックしましたが、プログラムのロジックは完璧に思えます。ファイルのコンパイルの順序はMyClass2
、実装で使用する前に定義する必要があります!
モジュールの代わりに「古い」 .h および .cpp ファイルを使用して、この正確なプログラムをコンパイルしようとしましたが、コンパイルして正常に実行されます。したがって、これらの新しいモジュールに関して何かが欠けていると思います。
モジュールの最初の公式提案 (10.7.5 項)を調べたところ、最初の提案には宣言された所有権宣言という名前の構造があり、そのような場合には完璧に見えました。基本的に、現在のモジュール内の別のモジュールが所有するエンティティをインポートできますが、モジュール自体はインポートしません。しかし、提案のその後の改訂では、その兆候はありません。絶対に何もありません。そして、新しい提案の「変更ログ」セクションでは、それは引用さえされていません。
循環依存が悪いとは言わないでください。私はしばしば彼らが悪いことを知っていますが、常にではありません. そして、あなたが彼らがいつも悪いと思っているとしても、私は経験則を求めているわけではありません. 私のコードが「古い」 .h + .cpp でコンパイルされ、新しいモジュールではコンパイルされない理由を尋ねています。リンカが の定義を認識しない理由MyClass2
。
編集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;
}
他のすべてのファイルは変更されません。