Can C++ modules in Visual Studio 2022 handle forward declarations?
The following code has a circular dependency that I want to break using a forward declaration, but the compiler doesn't seem to recognize that it refers to the same type as the full class declaration, so it doesn't compile. Am I doing something wrong?
main.cpp
import A;
int main()
{
CB cb;
CC cc;
cc.MyFunc3(cb);
return 0;
}
A.ixx
export module A;
export import :B;
export import :C;
A-B.ixx
export module A:B;
class CC;
export class CB {
public:
void MyFunc(const CC& cc) const;
};
A-B.cpp
module A;
import :B;
import std;
import :C;
void CB::MyFunc(const CC& cc)
{
std::cout << "Hello World B" << std::endl;
}
A-C.ixx
export module A:C;
class CB;
export class CC {
public:
void MyFunc1(const CB& cb) const;
};
A-C.cpp
module A;
import :C;
import std;
import :B;
void CC::MyFunc1(const CB& cb)
{
std::cout << "Hello World B" << std::endl;
cb.MyFunc(*this);
}
This is the error:
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(7,10): error C2511: 'void CC::MyFunc1(const CB &)': overloaded member function not found in 'CC'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.ixx(5,14):
1>see declaration of 'CC'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(10,5): error C2027: use of undefined type 'CB'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.ixx(3,7):
1>see declaration of 'CB'
1>C:\Users\peterB\repositories\hobby projecten\Hexanaut-AI\Hexanaut-AI\Hexanaut-AI\A-C.cpp(10,16): error C2671: 'CC::MyFunc1': static member functions do not have 'this' pointers
Relevant compiler options:
/std:c++latest /experimental:module
With 'Build ISO C++23 standard library modules' turned on.
You need to be more consistent about your
exportdeclarations. This includes forward declarations.CCandCBare both supposed to beexported. This means that the forward declarations of them should also beexported.One way to avoid excess repetition is to have a module interface partition for such declarations that all other partitions import:
The
exportinA-Bis not necessary, but it's good as a reminder.A-C.ixxshould also import:fwd.Note that my reading of the standard is that it should have given a compile error when compiling the module
A. That file importsA:B, which declaresCCas non-exported. When it importsA:Cthat declares it exported, that should have triggered [module.interface]/6:That "shall not be exported" translates to "ill-formed if the entity is redeclared as exported". But VC++ didn't do that apparently.
It does give an error eventually, but only when you try to use it. See, it seems to be translating your code such that there are two types named
CB: the exported one and the non-exported one. The objectcbis of the exported type, but the type used byCC::MyFunc3is the non-exported one. Since they are two different types, and no conversion operator is defined, you get an error.