SOLVED: Dynamic Template List

Started by
6 comments, last by RDragon1 18 years, 11 months ago
Thank you for the help! I am referring to VC++. Hello, I have a maybe rather easy problem but I tryed to solve it for the last few hours and I have absolutely no idea what I am doing wrong: I use a template class in my current program which is really neccessary, but there are two things I cant get to work: 1) I get a linker error when I compile my program. I already looked at different Tutorials and they tell me to put an instance of my template class into the source file. like: template class cList<cElement>; I did this, but now I get a warning ("(4660) template class instance already defined") - my only solution was to ignore it with #pragma warning (disable: 4660), but that does not seem correct. Is there another way to remove the linker error? 2) The template class itself is a dynamic list which should be able to add and remove items that are saved with pointers pointing to each other. The list saves the First and the Last items' addresses and every item is connected to the Next and the Previous item of the list with pointers (I posted my code below). This is not perfect, but very usefull for what I want to do. My problem is: I can add items to my template List, but I cannot remove items. Somehow it seems like the item I want to delete is not affected. What am I doing wrong? Here is the relevant part of my code:

//Generic List Class (in a header file)
template <class T>
class cList
{
private:
	T *First;	//First Element
	T *Last;	//Last Element

public:
	T *Add();			//Add Element: works!
	void Remove(T *obj);		//Remove Element with specified Address: doesnt work!
	cList(){ First = Last = 0 };	//Ctor
};


//Example for an Element class that could be used for the List (in a header file)
class cElement
{
public:
	cElement *Next;	//Next Element
	cElement *Prev;	//Previous Element
	cElement(){ Next = Prev = 0 };	//Ctor
};


//Remove function (in a source file)
template <class T>
void cList<T>::Remove( T *obj )
{
	//Check if Address of Element which should be removed is valid
	if( !obj )
		return;

	//Reassign Connections
	if( obj->Prev )
		obj->Prev->Next = obj->Next;
	if( obj->Next )
		obj->Next->Prev = obj->Prev;	

	//Delete Element
	delete obj;
	obj = 0;
}



Thank you for your help! rgds, Phex [Edited by - Phex on May 24, 2005 2:56:11 PM]
Advertisement
1) I get a linker error when I compile my program.

About a missing cList::Remove function, I presume? [smile]

//Remove function (in a source file)

Function template definitions and class template member function definition need to go into the header file.

I already looked at different Tutorials and they tell me to put an instance of my template class into the source file. like: template class cList<cElement>;

Right, the other option, if you don't want to put the function in the header file is to specify, in the source file that contains the member function definitions, which versions of the class template you're going to use in your program, so that the compiler actually goes and generate the corresponding member functions. So if you write class cList<cElement>; (no template keyword), the compiler will know that it needs to generate the member functions for that version of the class template. You just need to make sure that you add that for each and every version you will ever want to use, and make sure they actually are in the same source file as where the member functions are defined (since the compiler actually needs the source code AND to know which version of the class template it is going to use at the same time).

Which is why putting the member functions in the the header file makes things easier, as the compiler always has everything it needs.

And no, in the case of function templates and class template member functions, just as with inline functions, putting the definition in a header file (i.e. causing it to be multiply defined, once in each translation unit that includes the header file), is not an error. For "normal" non-inline, non-template functions, it is an error.

2) The template class itself is a dynamic list which should be able to add and remove items that are saved with pointers pointing to each other.

C++ already has a list class template, std::list defined in the <list> standard header, use it.

This is not perfect, but very usefull for what I want to do.

I gather you aren't then just trying to create a list class for learning purposes. You therefore have no excuse not to use std::list. [evil]

Somehow it seems like the item I want to delete is not affected.

Well, the obj = 0; statement won't affect the original pointer variable, only the local copy in your Remove function. The rest should work normally.


"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Thank you for the quick answer!

1) I tried to put the template function definitions into a header file, but I still get a linker error: error LNK2001. When I put template class cList<cElement>; in a source file, it works again together with a warning.

2) I will look closer at the predefined list class if I cant get any further, but it seems too complex for my purposes. Maybe it would be easier to ask how I can create an operation that does what obj = 0 is meant to do?
Quote:Original post by Phex
1) I tried to put the template function definitions into a header file, but I still get a linker error: error LNK2001.


Ok, what precisely is the error message?

Quote:2) I will look closer at the predefined list class if I cant get any further, but it seems too complex for my purposes.


It's just a stupid linked list, how can it be 'too complex' [smile] If you're referring to its interface, it's just that it is unfamiliar. All the standard C++ containers have a similar interface, you would do well to learn it, it'll save you much trouble down the road.

Quote:Maybe it would be easier to ask how I can create an operation that does what obj = 0 is meant to do?


Simply pass obj by reference instead of by value:

template <class T> void cList<T>::Remove( T*& obj )

Any modifications of the obj variable will be reflected on to the pointer you really passed to the function.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
1) My compilation log is in German, but it says something like
Linking...
sourcefile.obj : error LNK2001: Non-resolved external symbol "public: class cElement * __thiscall cList<cElement>::Add(void)" (?Add@?$cList@VcElement@@@@QAEPAVcElement@@XZ)
fatal error LNK1120: 1 non-resolved external reference
when I try to execute cList::Add().

2) Remove() works perfectly now!
Probably because Add() is defined, but not implemented.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
Quote:Original post by CodeMunkie
Probably because Add() is defined, but not implemented.


You mean declared, but not defined, of course ;)
It's hard to say what the state of your code is at this point, but the function definitions have to be included with the header file, in the case of templates (until there is widespread support of the export keyword, at least). There are a few ways to do it - you can put the function definitions right inside the class definition

template< typename T>struct SomeStruct{  void SomeMethod()  {     //function definition  }};


or:

template< typename T>struct SomeStruct{  void SomeMethod();};template< typename T>void SomeStruct< T>::SomeMethod(){   //function definition}


or:

in SomeStruct.h

template< typename T>struct SomeStruct{  void SomeMethod();};#include "SomeStruct.cpp"


in SomeStruct.cpp NOTE: don't compile this source file into your project

template< typename T>void SomeStruct< T>::SomeMethod(){   //function definition}


I personally prefer the first method, but to each his own.

This topic is closed to new replies.

Advertisement