Can the private module fragment be used to break cyclic dependencies in the same way that implementation source files can? This example is using Visual Studio 2022 Preview.
This is an example that compiles successfully without the private module fragment and how I expect you would solve this issue.
ModuleA.ixx
export module ModuleA;
import ModuleB;
export class ClassA
{
public:
ClassB foo;
void sayHello();
};
ModuleA.cpp
module;
#include <iostream>
module ModuleA;
void ClassA::sayHello()
{
std::cout << "Hello" << std::endl;
}
ModuleB.ixx
export module ModuleB;
export class ClassB
{
public:
void sayHello();
};
ModuleB.cpp
module ModuleB;
import ModuleA;
void ClassB::sayHello()
{
ClassA bar;
bar.sayHello();
}
main.cpp
import ModuleB;
int main()
{
ClassB baz;
baz.sayHello();
return 0;
}
This is an example using the same main.cpp and the private module fragment that results in a cyclic dependency error.
ModuleA.ixx
export module ModuleA;
import ModuleB;
export class ClassA
{
public:
ClassB foo;
void sayHello();
};
module :private;
import <iostream>;
void ClassA::sayHello()
{
std::cout << "Hello" << std::endl;
}
ModuleB.ixx
export module ModuleB;
export class ClassB
{
public:
void sayHello();
};
module :private;
import ModuleA;
void ClassB::sayHello()
{
ClassA bar;
bar.sayHello();
}
So, what is the difference between these two implementations and why does one work but the other doesn't?
CodePudding user response:
Your original example worked because each of the four files were separate translation units (TU). The implementation units each required the other modules' interface units, but the interface units themselves had no dependencies on the implementation units. So both interface units could be compiled before either implementation unit. Thus both module interfaces are available to both implementation units.
By combining each module's interface and implementation units into the same file, you put them in the same TU. The fact that part of it is in a private module fragment changes nothing about this. They are compiled at the same time since they're all part of the same TU. So the import ModuleB
directive must be processed while compiling ModuleA
, which means that ModuleB
must be compiled, which requires processing the import ModuleA
directive.
Which is a cycle.
Put simply, private module fragments are not separate files to be processed by the compiler.