10

私はこの問題に何日も頭を悩ませてきました.新しい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を前方宣言することはできません。これは、 MyClass1inでタイプ の具象オブジェクトを使用しているmySubmodule2ためです。MyClass2MyClass1

私はこの行でコンパイルします: cl /EHsc /experimental:module /std:c++latest mySubmodule1.ixx mySubmodule2.ixx myModule.ixx mySubmodule1Impl.cpp mySubmodule2Impl.cpp Source.cppwhere Source.cppis just the main.

悪名高いエラー C2027: use of undefined type 'myNamespace::MyClass2' in mySubmodule1Impl.cppand mySubmodule2Impl.cppat the lines where I use が表示されますMyClass2。さらに、コンパイラは、前方宣言があるMyClass2inの宣言を確認するように指示します。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;
}

他のすべてのファイルは変更されません。

4

3 に答える 3