Consider this program:
MyType1.ixx:
export module MyType1;
namespace MyNamespace {
class MyType2;
export class MyType1 {
public:
MyType1(MyType2* MyType2);
void Print();
private:
MyType2* MyType2Instance{};
};
}
Module1.cpp:
module MyType1;
import <iostream>;
import MyType2;
namespace MyNamespace {
MyType1::MyType1(MyType2* MyType2) {
MyType2->Print();
}
void MyType1::Print() {
std::cout << "Hello MyType1\n";
MyType2Instance->Print();
};
}
MyType2.ixx:
export module MyType2;
import <iostream>;
namespace MyNamespace {
export class MyType2 {
public:
void Print() {
std::cout << "Hello MyType2\n";
}
};
}
Main.cpp:
import MyType1;
import MyType2;
using namespace MyNamespace;
void main() {
MyType2 MyType2{};
MyType1 MyType1(&MyType2);
MyType1.Print();
MyType2.Print();
}
Doing this gets me an error in Visual Studio: Error C2665 'MyNamespace::MyType1::MyType1': no overloaded function could convert all the argument types.
One solution is to also export the forward-declared class MyType2 in MyType1.ixx:
export module MyType1;
namespace MyNamespace {
export class MyType2;
export class MyType1 {
public:
MyType1(MyType2* MyType2);
private:
MyType2* MyType2Intance{};
};
}
Another solution is to forward-declare the MyType2 class before the export module MyType1 line:
namespace MyNamespace {
class MyType2;
}
export module MyType1;
namespace MyNamespace {
export class MyType1 {
public:
MyType1(MyType2* MyType2);
private:
MyType2* MyType2Intance{};
};
}
The question is why does this work and how does this work, and why a more brain-friendly and intuitive solution of just forward-declaring the class inside the module doesn't work?


What you're trying to do doesn't really make sense. And the fact that you have decided to name your modules the same as your classes makes it extremely difficult to explain what's going on (please stop doing this; modules should not be single-classes in size. There's no point in making modules that small).
In any case, the principle issue is that, if you put a declaration in a module, the module system thinks that you mean it. By declaring
MyNamespace::MyType2inside of the moduleMyType1, that means that the module system thinks that...MyNamespace::MyType2is part ofMyType1.Therefore, when it gets around to compiling the
MyType2module, when it finds a class namedMyNamespace::MyType2, it believes that this is a different class from the one local to theMyType1module.Because it is.
Therefore, when your
mainfunction createsMyNamespace::MyType2, this is of the type from theMyType2module (since nobody outside ofMyType1has access to theMyType1's non-exported stuff). Since this is a different type from the one used byMyNamespace::MyType1, the compiler cannot convert pointers to two unrelated type.What you have is that the module
MyType1has a dependency on the moduleMyType2. It should importMyType2in its primary module interface. And since you can't useMyType1without having aMyType2, it should probablyexport importit.Or better yet... don't make these into separate modules. They can be in separate module files, but they should all be part of the same module.