Templated Function results in Circular Inclusion

This topic is 863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have a tricky circular inclusion issue that I dont know how to solve. To sum up:

IApp inherits from Component
Component implements a templated function in its header file that uses IApp::registerForEvent

What technique or method can I use to fix/avoid this circular inclusion?

class Component;
class IApp;

class Component
{
IApp* app;

// Error: Invalid use of incomplete type 'class IApp'
template<typename T>
void registerEvent(const int& evtId, Status (T::*func) (int))
{
auto res = std::bind(func, (T*)this, std::placeholders::_1);
app->registerForEvent(evtId);
}
};

class IApp : public Component
{
public:
void registerForEvent(const int& evtId)
{
printf("IApp::registerForEvent\n");

// ...
}
};

Edited by gretty

Share on other sites

While Status is undefined, your code compiles for me on VS2013.

Share on other sites

I'll assume this code is somewhat incomplete, since you aren't using res.

I can't think of anything to fix it with the code you are currently using, however, I notice you are using a raw function pointer. Do you have access to std::function? (introduced with c++11). In that case, you could replace the raw function pointer with an std::function, which avoids having to use a template function to pass along the template parameter in the first place. Then, you can forward declare IApp without any problems. Even without c++11, the boost library should have this as well.

Another solution is to have another function in Component, that simply forwards to registerForEvent on the the instance of IApp. Since you can place the definition of that function in your cpp, you only need to include IApp in Component's cpp and keep it forward declared in Component's header file.

On a side-note, I can't help but comment on the overall design, unless this is for demonstration purposes only. Why does the base class need to know about one of its derived classes in the first place? I think an even better solution would be to reconsider your design.

Giving some clarification on what you want to accomplish is useful as well, so that others can share their thoughts.

Share on other sites

So since I also got it to compile the way you posted, I assume the following:

- Component and IApp are actually in different header files

- Your code at some place usinng the Component::registerEvent-function only includes "Component.h", without including "IApp.h"?

If this is true, you can do it this way: Since apparently you cannot have circular-inclusions of inheriting classes, you need to create a non-templated function in your Component-class, and define it in the cpp. There, you can include "IApp.h", and that is where you call its functions.

// Component.h

#pragma once
#include "IApp.h"
class IApp;

class Component
{
IApp* app;

// Error: Invalid use of incomplete type 'class IApp'
template<typename T>
void registerEvent(const int& evtId, int(T::*func) (int))
{
auto res = std::bind(func, (T*)this, std::placeholders::_1);
registerAppEvent(eventId);
}

void registerAppEvent(int eventId);
};

// Component.cpp
#include "Component.h"
#include "IApp.h"

Component::registerAppEvent(int eventId);
{
app->registerForEvent(eventId);
}


If my preassumption was wrong, this might not present a solution however.

On a side-node, any reason why you pass evtId as const int&? In case of small primitive types, you should always pass them by value instead of const-reference unless totally require otherwise, since there is absolutely no speed-gain by doing so.

Edited by Juliean

Share on other sites
Why is IApp inheriting from Component? From what we can tell here, a Component is something that has a pointer to IApp. Is that just going to be null for the actual IApp, or will it point to itself? I have a feeling you don't really need to inherit from it.

Circular references aren't always bad, but they are still something you can try to avoid.

If necessary, you can split the definition of the templated function out of the header file defining the class, and put it in its own file. Or, you could put both of these classes in the same header and just do everything in the right order. The two classes depend on each other being included together anyway.

Still, this kind of problem is a sign that maybe your design needs rethinking.

1. 1
2. 2
3. 3
Rutin
16
4. 4
5. 5
JoeJ
12

• 10
• 9
• 14
• 10
• 25
• Forum Statistics

• Total Topics
632646
• Total Posts
3007637
• Who's Online (See full list)

There are no registered users currently online

×