Click here to Skip to main content
15,880,469 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm trying to figure out the basics of getting the forward declaration problem solved in modules. I believe any reasonably sized project needs classes to hold references or pointers to other classes. So the bare bones of the problem, expressed without modules is:

C++
class B;

class A {
   private:
      B* b;
   public:
      void setB(B* b_) { b = b_; }
   };

class B {
   private:
      A* a;
   public:
      void setA(A* a_) { a = a_; }
   };


int main() {
   A a;
   B b;
   a.setB(&b);
   b.setA(&a);
   return 0;
   }

Since I read that modules can include header files, my first attempt in Visual Studio 2019 (updated to 16.11.9) is:

C++
//Main unit:
import B;

class A {
   private:
      B* b;
   public:
      void setB(B* b_) { b = b_; }
   };

int main() {
   A a;
   B b;
   a.setB(&b);
   b.setA(&a);
   return 0;
   }

C++
//B.ixx:
module;
export module B;

#include "A_declaration.h"

export class B {
   private:
      A* a;
   public:
      void setA(A* a_) { a = a_; }
   };

and

C++
//A_declaration.h:
#pragma once

class A;   //Just a forward declaration

Upon compilation, at the 'b.setA(&a);' line this gives: Error C2664 'void B::setA(A *)': cannot convert argument 1 from 'A *' to 'A *'

What is the correct way to do this?

What I have tried:

What I've outlined above. And some reading. But not enough to find the solution, unfortunately.
Posted
Updated 21-Jan-22 9:55am
v2

I am not sure where you got those import and export lines from. The usual way inb C++ is to put the declarations in the header file and the implementation in the .cpp file. Something like:
C++
// Something.h
//
// if CSomething includes a reference to COtherthing then you can add
class COtherthing; // forward reference. But it is a bad idea for COtherthing to back reference CSomething. That is a design issue.

class CSomething
{
private:
    int m_somevariable;
    COtherthing* other;

public:
    CSomething(); // constructor declarations
    ~CSomething(); // destructor declarations

    int getSomething(); // function declaration
};

The definitions (implementation) then goes into the .cpp file
C++
#nclude "Something.h"

int main()
{
    CSomething something; // instantiate an object of the class

    int foo = something.getSomething(); // gets a value
}
 
Share this answer
 
Comments
David O'Neil 21-Jan-22 4:04am    
I understand where you are coming from, but I am trying to wrap my head around modules, which are fairly new in C++: https://docs.microsoft.com/en-us/cpp/cpp/modules-cpp?view=msvc-170. My initial code example is compilable, and I know how to split that up into .cpp/h files without any problems. It is only when I try to replicate it with modules that the problems come up.
Richard MacCutchan 21-Jan-22 5:33am    
Sorry, I misunderstood the question. My experience of modules is a number approaching (but not equal to) zero. But whether you use modules, or traditional headers, the issues are very similar.
CPallini 21-Jan-22 4:16am    
Hey man, you need to get more current!
https://vector-of-bool.github.io/2019/03/10/modules-1.html
(actually this is the very first time I hear about C++ modules... )
Richard MacCutchan 21-Jan-22 5:32am    
I had heard of them before today but have not actually tried to use them yet. Maybe tomorrow :).
Thanks to c++20 - C++ Modules Forward Declaring Entity from Another Module - Stack Overflow[^], I got a solution working. It is:

C++
//main.cpp:
import A;
import B;

int main() {
   A a;
   B b;
   a.setB(&b);
   b.setA(&a);
   return 0;
   }


C++
//A.ixx:
export module A;

export class B;

export class A {
   private:
      B* b;
   public:
      void setB(B* b_) { b = b_; }
   };


C++
//B.ixx:
export module B;

export class A;

export class B {
   private:
      A* a;
   public:
      void setA(A* a_) { a = a_; }
   };


The only problem is that although it works, Visual Studio Intellisense is showing errors that "incomplete class type "A" is not allowed" on both "A a;" and "a.setB(&b);" lines. Those errors will be annoying to see, even though the compiled program doesn't treat them as errors! :rolleyes:

If I rearrange the 'import A' 'import B' lines, then the errors become 'incomplete class type "B" is not allowed' on the 'b' lines. :anotherRolleye:

Other than the errors that aren't errors, I like this way better because it eliminates headers. Unless I'm overlooking something else.
 
Share this answer
 
Comments
David O'Neil 21-Jan-22 16:17pm    
Another thing to consider, is that Visual Studio seems to be real flakey with this approach. The Package Server keeps locking 'A.ifc' and 'B.ifc' files, so I have to try multiple approaches to delete them, in order to recompile when things change. Last method that worked after others wouldn't is to close VS, wait a few secs for all processes to close in Task Manager, then delete them in File Explorer, then reopen Visual Studio and rebuild. Grrrr.... Frustrating to say the least. It doesn't seem like modules are quite there yet. (I installed VS 2022 to try it - same problems there.)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900