forward declaration and template function error

I am a new member of cplusplus forum and this is my first post here.
Currently I have a frustrating problem with forward declaration and template function. Below is the snippet of the code:

class TaskScheduler; --> //forward declaration of ‘struct TaskScheduler’
//
//

class TaskEvent {
//
//
};

class HostTask {
//
//
};

template<class T> inline HostTask*
findT(TaskScheduler* tss, T* e)
{
map<int, HostTask*>::iterator it;
bool bEq = false;
for(it = tss->tasks_.begin(); it != tss->tasks_.end(); it++) { --> //error: invalid use of incomplete type ‘struct TaskScheduler’
if(dynamic_cast<TaskEvent*>(e))
bEq = dynamic_cast<TaskEvent*>(e)->equal(it->second->ev_);
else if(dynamic_cast<HostTask*>(e))
bEq = dynamic_cast<HostTask*>(e)->equal(it->second);
if(bEq) {
return it->second;
}
}
return NULL;
}
//

//class TaskScheduler definition
class TaskScheduler : virtual public HCIEventsHandler {
friend HostTask* findT<TaskEvent>(TaskScheduler* tss, TaskEvent* e); //findT function is used here
//
//
};

Here is the error message that I've got which is shown in the code as well:
./bt-taskscheduler.h:159: error: forward declaration of ‘struct TaskScheduler’
./bt-taskscheduler.h:229: error: invalid use of incomplete type ‘struct TaskScheduler’

Could anybody show me what is going wrong in this code? Any help is appreciated..
Last edited on
Why don't you move findT after TaskScheduler?
You can't use members of a class which wasn't declared properly

Also, use [code][/code] tags
If you use templates with RTTI, you get the worst of both worlds, code bloat and the run-time cost of using RTTI.

You'd be better off having a templated version that is specific to your familt of types or going for a more traditional OO hierarchy.
Thank you all for your reply :)
@Bazzy: did you mean to move the findT after the complete TaskScheduler class? If it's so I got another error which says: ‘findT’ is neither function nor member function; cannot be declared friend.
@kbw: could you please explain me what you mean about "templated version that is specific to your familt of types or going for a more traditional OO hierarchy"?
Thank you..
Forward declare findT
ok, I'll try it..
As Bazzy suggested, it's the order of declaration that matters. I've filled in some minimal code to make it compile.

Looking further at what you have now, I think you need a static way to determine what kind of T is passed to findT. Taken from Alexandrescu's Loki, IsSameType will do it for you. I've added a findK to demonstrate. At least, this way you won't have the RTTI runtime overhead.

I still think the overall design needs to be revised.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <map>

class HCIEventsHandler {};

class TaskScheduler;

class TaskEvent
{
	int ev_;

public:
	bool equal(int);
};

class HostTask
{
	bool equal(HostTask*);
};

template <class T>
HostTask* findT(TaskScheduler* tss, T* e);

template <class T>
HostTask* findK(TaskScheduler* tss, T* e);

class TaskScheduler : public HCIEventsHandler
{
	template <>
	friend HostTask* findT(TaskScheduler* tss, TaskEvent* e);

	std::map<int, HostTask*> tasks_;
};

template<class T>
HostTask* findT(TaskScheduler* tss, T* e)
{
	for (std::map<int, HostTask*>::iterator it = tss->tasks_.begin(); it != tss->tasks_.end(); ++it)
	{
		bool bEq = false;

		if (dynamic_cast<TaskEvent*>(e))
			bEq = dynamic_cast<TaskEvent*>(e)->equal(it->second->ev_);
		else if(dynamic_cast<HostTask*>(e))
			bEq = dynamic_cast<HostTask*>(e)->equal(it->second);

		if (bEq)
		{
			return it->second;
		}
	}

	return NULL;
}


template <typename T, typename U>
struct IsSameType
{
    enum { value = false };
};

template <typename T>
struct IsSameType<T, T>
{
    enum { value = true };
};

template<class T>
HostTask* findK(TaskScheduler* tss, T* e)
{
	for (std::map<int, HostTask*>::iterator it = tss->tasks_.begin(); it != tss->tasks_.end(); ++it)
	{
		bool bEq = IsSameType<HostTask, T>::value
						? e->equal(it->second)
						: e->equal(it->second->ev_);

		if (bEq)
		{
			return it->second;
		}
	}

	return NULL;
}

Last edited on
Hi kbw.. thank u a lot for your suggestion.. that really works!
Topic archived. No new replies allowed.