Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Community » Newbie corner » C++ templated class referencing each other
C++ templated class referencing each other [message #55096] Sun, 11 October 2020 00:45 Go to next message
Xemuth is currently offline  Xemuth
Messages: 387
Registered: August 2018
Location: France
Senior Member
Hello,

I have 2 class :

Object.h
#include "ComponentManager.h"
class Object{
    public:
      Object() : componentManager(*this){}
     /*
         Many public things
     */
    private:
       ComponentManager componentManager;
};

ComponentManager.h

class Object;

class ComponentManager{
    public:
     ComponentManager(Object& _object) : object(_object){}

     template<class T> T& function1(...) 
     /*
        Many templated function that force me to write declaration in this .h file
     */
    private:
      Object& object;
}


My both class are made to work together, ComponentManager make no sens without an object etc...
All is fine and work well. Untill, in one of my templated function in ComponentManager, I need to use my Object reference to call a function of object :

template <class T> T& CreateComponent(bool active, int position){
/*
   Working code
*/
Object& obj = object.GetScene().GetObjectManager().GetObjects()[i];  //This line is problematic
/*
   Working code
*/
}

since I need to use some function of Object, compiler need Object declaration. But no way I can give to ComponentManager the implementation of object because Object need Compoment implementation. I can't split my CompomentManager into .h and .cpp so I'm kind of blocked.

Someone have an idea of how I could trick the compiler ? do I will need to change the way my architecture work (only for a function Sad).

here is the complete problematic chunck of code :
for(int i = 0; i <  object.GetScene().GetObjectManager().GetObjectsCount(); i++){
	Object& obj = object.GetScene().GetObjectManager().GetObjects()[i];
	if(&obj != &object){
		if(obj.GetComponentManager().HasComponent<T>()){
			throw Exc("...");
		}
	}
}


I have thinked about externalise in a .cpp a function (not templated) which do the job and then I could have include in the .cpp the Object defintion but since I need to call some Function with my templated class argument, I dont think I can work at all.

Re: C++ templated class referencing each other [message #55099 is a reply to message #55096] Sun, 11 October 2020 04:25 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 536
Registered: March 2007
Contributor
This hack seems to compiles in CLANG. I am sure there are smarter and more standard ways to serve your purpose.

Object.h
#ifndef _TestTemplate_Object_h_
#define _TestTemplate_Object_h_

#include "CompManager.h"
class Object{
    public:
      Object() : componentManager(*this){
      }
      
      void SayHello(){ componentManager.CreateComponent<int>(false,100); }
      Object& GetObject(){ return *this;}
     /*
         Many public things
     */
    private:
       ComponentManager componentManager;
};
#include "CompManagerEx.h"
#endif


CompManager.h
class Object;

class ComponentManager{
    public:
     ComponentManager(Object& _object) : object(_object){}
     
     template <class T> T& CreateComponent(bool active, int position);

     /*
        Many templated function that force me to write declaration in this .h file
     */
    private:
      Object& object;
};


CompManagerEx.h

template <class T> T& 
ComponentManager::CreateComponent(bool active, int position)
{
	static T t;
/*
   Working code
*/
	Object& obj=object.GetObject();  //This line is problematic
	LOG("Hello inside ComponentManager::CreateComponent(bool active, int position)");
/*
   Working code
*/
	return t;
}


test.cpp
#include <Core/Core.h>

#include "Object.h"

using namespace Upp;

CONSOLE_APP_MAIN
{
	Object obj;
	obj.SayHello();
}

[Updated on: Sun, 11 October 2020 04:27]

Report message to a moderator

Re: C++ templated class referencing each other [message #55100 is a reply to message #55096] Sun, 11 October 2020 04:36 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 536
Registered: March 2007
Contributor
Notice that I essentially put everything in the same header file (equivalently).

Also, if your can guarantee that ComponentManager Will be the first member variable (because why-not and you should put a static_assert to avoid accidently add some other member variable in front it subsequently), you can probably save the
Object& obj;

member variable in the ComponentManager class. Simply define it like:
class Object;

class ComponentManager{
    public:
     ComponentManager(){}
     
     template <class T> T& CreateComponent(bool active, int position);

     /*
        Many templated function that force me to write declaration in this .h file
     */
    private:
      Object& object(){
          return *reinterpret_cast<Object*>(this);
      }

};


And change other part of your code accordingly.


PS: If your Object class is virtual, some compiler might put vtable at this. In this case, above hack will be problematic. I will consider to let Object to privately inherit from ComponentManager.

[Updated on: Sun, 11 October 2020 04:45]

Report message to a moderator

Re: C++ templated class referencing each other [message #55107 is a reply to message #55096] Sun, 11 October 2020 16:38 Go to previous messageGo to next message
Xemuth is currently offline  Xemuth
Messages: 387
Registered: August 2018
Location: France
Senior Member
Hello Lance,

Thanks for the time you take.

CompManagerEx.h


Did not worked for me. I had compilation error saying it was impossible to define/redefine CreateComponent because it was out of Upp (even if it was in Upp namespace)

Quote:
Notice that I essentially put everything in the same header file (equivalently).

It dont work either, it fix the circulare dependencies between my problematic code and Object definition, however it also need the Scene object definition. If I include this definition in object.h file (since ComponentManager is in object.h file) it will lead to the same problem, circular dependencies include (because Scene include ObjectManager which include Object which will include Scene...)


Quote:
Also, if your can guarantee that ComponentManager Will be the first member variable (because why-not and you should put a static_assert to avoid accidently add some other member variable in front it subsequently), you can probably save the
Object& obj;

member variable in the ComponentManager class. Simply define it like:
class Object;

class ComponentManager{
public:
ComponentManager(){}

template <class T> T& CreateComponent(bool active, int position);

/*
Many templated function that force me to write declaration in this .h file
*/
private:
Object& object(){
return *reinterpret_cast<Object*>(this);
}

};


And change other part of your code accordingly.


I dont really understand this solution, are you meaning inherriting privatly/publicly Object from componentManager ? if yes I'm afraid the problem will remain since circulare reference between Scene and Object.h will appear. Maybe my architecture is bad and should be change to something like Opaque pointer
Re: C++ templated class referencing each other [message #55108 is a reply to message #55096] Sun, 11 October 2020 16:46 Go to previous message
Xemuth is currently offline  Xemuth
Messages: 387
Registered: August 2018
Location: France
Senior Member
OK I retried use of ComponentManagerEx.h and it worked fine, thanks Lance you fixed my probleme.

[Updated on: Sun, 11 October 2020 17:19]

Report message to a moderator

Previous Topic: operation involving "\\" x "\" characters in directories and files
Next Topic: Shrila Prabhupada Sanskrit Slovary
Goto Forum:
  


Current Time: Fri Jun 21 01:06:20 CEST 2024

Total time taken to generate the page: 0.03345 seconds