Problem With Passing a Class as a type for a template

Started by
5 comments, last by dave 19 years, 5 months ago
I have written a linked list objects and it works well until u pass in a class as a type when initiating the list. So i have:

class a;  // without body for this example.

linked_list<a> newList;


I get the errors: f:\developement\my documents\program\salamol v201\linked_list.h(25) : error C2512: 'LIST' : no appropriate default constructor available f:\developement\my documents\program\salamol v201\linked_list.h(24) : while compiling class-template member function '__thiscall linked_list<class file>::linked_list<class file>(void)' i do have 1 constructor, which is

	linked_list() : listInitiated(false)
	{
		InitLinkedList();
	}


It seems if i change the creation line to: linked_list<a> newList(); it compiles and links but i cant then use the "newList." syntax on the created list object. Can anyone help with this? ace
Advertisement
You'll probably have to show more code, what you have doesn't really give any clues to what the problem is.

Oh and this line:
linked_list<a> newList();
doesn't declare an object; it declares an function called newList that returns a linked_list<a> object. It's one of C++'s more annoying parsing rules.
ok so here is the complete source to the whole project im working on.

linked_list.h
#ifndef	_S_LINKED_LIST_#define	_S_LINKED_LIST_#include <stdio.h>#include <stdlib.h>template <class TYPE>class linked_list{private:	// MEMBER DATA	struct LIST	{		TYPE _item;		unsigned long nodeNumber;				LIST* next;		LIST* prev;	} start;public:	linked_list() : listInitiated(false)	{		InitLinkedList();	}	virtual ~linked_list()	{		if (listInitiated == true)		{			KillList();		}	}	// MEMBER DATA	LIST*	_node;	// MEMBER METHODS	void _AddNode(TYPE* _inPtr)		{ if (_inPtr != NULL) AddNode(_inPtr);	};	void _RemoveNode()				{ RemoveNode();							};	void _GotoStart()				{ GotoStart();							};	void _GotoEnd()					{ GotoEnd();							};	void _IncNode()					{ IncNode();							};		void _DecNode()					{ DecNode();							};	void _KillList()				{ KillList();							};	void _SwapThisNext()			{ SwapThisNext();						};	void _SwapThisPrev()			{ SwapThisPrev();						};	unsigned long _EnumNodes()		{ return numNodes;						};private:	// MEMBER DATA	bool				listInitiated;	unsigned long		numNodes;	// MEMBER METHODS	inline void InitLinkedList()	{		start.next = NULL;		_node = &start;		listInitiated = true;		numNodes = 0;	}	inline void AddNode(TYPE* _inPtr)	{		if (listInitiated == true)		{			LIST* lastNode;			// allocate memory for the next list node			_node->next = (struct LIST *) malloc(sizeof(struct LIST));			// increment the number of node counter			numNodes++;			// set a temporary pointer to point to the current node			lastNode = _node;			// move to the next node			_node = _node->next;			// set the prev pointer to the last node			_node->prev = lastNode;			// set the node number			_node->nodeNumber = numNodes;			// copy the info accross			memcpy( &_node->_item, _inPtr, sizeof(_node->_item) );						// set the pointer to the next node to NULL			_node->next = NULL;		}	}	inline void GotoStart()	{		if (listInitiated == true)		{			_node = &start;			_node = _node->next;		}	}	inline void GotoEnd()	{		if (listInitiated == true)		{			/// slow method for getting to teh last node, REDO			_node = &start;			_node = _node->next;						while( _node->next != NULL )			{				_node = _node->next;			}		}	}	inline void IncNode()	{		if (listInitiated == true)		{			if (_node->next != NULL)			{				_node = _node->next;			}		}	}	inline void DecNode()	{		if (listInitiated == true)		{			if (_node->prev != NULL)			{				_node = _node->prev;			}		}	}	inline void KillList()	{		if (listInitiated == true)		{			_node = &start;			_node = _node->next;			if (_node != NULL)			{				while (_node->next != NULL)				{					start.next = _node->next;					free(_node);					_node = start.next;				}			}			free(_node);			listInitiated = false;		}	}	inline void RemoveNode()	{		LIST* currentNext;		LIST* prev;		currentNext = _node->next;		prev = _node->prev;		_node = _node->prev;		free(_node->next);		_node->next = currentNext;		numNodes--;	}	inline void SwapThisNext()	{		_swap(&_node->_item, &_node->next->_item);	}	inline void SwapThisPrev()	{		_swap(&_node->_item, &_node->prev->_item);	}		template <class T>	void _swap(T* inA, T* inB)	{		T temp = NULL;		temp = *inA;		*inA = *inB;		*inB = temp;	}};#endif	_S_LINKED_LIST_


main.cpp
#include "file.h"#include "linked_list.h"int main (void){	FILE* fp = fopen("C:\\Documents and Settings\\Dave\\Desktop\\star.bmp", "rb+");	file	newFile("C:\\Documents and Settings\\Dave\\Desktop\\star.bmp", "rb+");	return 0;}


The contents of the file class are irrelevent so i wont bother posting. But thats the 2 files. There is no body file forht elinked_list class cos its a template.

Any help is appreciated, thanx

ace
Well, look at your list node struct. It stores an object of the templated type by value, and has no constructor, which means it will use the default constructor for the templated type. If the type that you pass the template doesn't have a default constructor or is an incomplete type, the constructor will fail to compile since the compiler can't apply the default constructor rules.
here, ill post the file class.

file.h
#ifndef _FILE_#define _FILE_const unsigned int FILE_PATH_SIZE			= 400;const unsigned int FILE_NAME_SIZE			= 200;const unsigned int FILE_EXT_SIZE			= 5;const unsigned int FILE_ACCESS_MODE_SIZE	= 5;#include <stdio.h>#include <string.h>class file{public:	file();	file(char* filePath, char* accessMode);	virtual ~file();	FILE* GetFilePointer();private:	void OpenFile();	void CloseFile();	void GetFileNameFromPath();	void GetExtensionFromPath();	void DetermineFileSize();	FILE*	fp;	unsigned long	fileSize;	char			filePath[FILE_PATH_SIZE];	char			fileName[FILE_NAME_SIZE];	char			fileExt[FILE_EXT_SIZE];	char			fileAccessMode[FILE_ACCESS_MODE_SIZE];	bool	fileOpen;};#endif //_file_


file.cpp
#include "file.h"////////////////////////////////////////////////////////////////////////////////////////////	Name:	file()//	Params:	filePath	- pointer to the incoming path//			accessMode	- pointer to the incoming access mode//	Desc:	Contructor for the file class. Checks the validity of the incoming strings,//			sets the local file data tot eh incoming values and calls the open file func.//////////////////////////////////////////////////////////////////////////////////////////file::file(char* filePath, char* accessMode){	if ( (filePath != NULL) && (accessMode != NULL) )	{		this->fileOpen = false;		strcpy(&this->filePath[0], filePath);		strcpy(&this->fileAccessMode[0], accessMode);		OpenFile();	}}////////////////////////////////////////////////////////////////////////////////////////////	Name:	~file()//	Params:	N/A//	Desc:	Destructor for the file class. Calls the CloseFile() function when the //			any objects of this class go out of scope.//////////////////////////////////////////////////////////////////////////////////////////file ::~file(){	CloseFile();}////////////////////////////////////////////////////////////////////////////////////////////	Name:	OpenFile()//	Params:	N/A//	Desc:	After checking whether this file has already been opened, opens if it hasn't//			been opened and sets the value of fileOpen accordingly.//////////////////////////////////////////////////////////////////////////////////////////void file::OpenFile(){	if (fileOpen == false)	{		fp = fopen(&filePath[0], &fileAccessMode[0]);		if (fp != NULL)		{			fileOpen = true;			GetFileNameFromPath();			GetExtensionFromPath();			DetermineFileSize();		}	}}////////////////////////////////////////////////////////////////////////////////////////////	Name:	GetFilePointer()//	Params:	N/A//	Desc:	This function returns pointer returns the member file pointer to the calling//			class only if it is valid, otherwise NULL is returned.//////////////////////////////////////////////////////////////////////////////////////////FILE* file::GetFilePointer(){	if (fileOpen == true)	{		return fp;	}	return NULL;}////////////////////////////////////////////////////////////////////////////////////////////	Name:	CloseFile()//	Params:	N/A//	Desc:	This function closes the file pointed to by the member file pointer only if//			the file has been opened.//////////////////////////////////////////////////////////////////////////////////////////void file::CloseFile(){	if (fileOpen == true)	{		fclose(fp);		if (fp == NULL)		{			fileOpen = true;		}	}}////////////////////////////////////////////////////////////////////////////////////////////	Name:	GetFileNameFromPath()//	Params:	N/A//	Desc:	This function is used to extract the file name//////////////////////////////////////////////////////////////////////////////////////////void file::GetFileNameFromPath(){	unsigned long	lengthOfPath	=	0;	unsigned long	pathPosPtr		=	0;	lengthOfPath = strlen(&filePath[0]);	for (	pathPosPtr = (lengthOfPath - 1); 			pathPosPtr >= 0; 			pathPosPtr--)	{		if ( filePath[pathPosPtr] == '\\')		{			strcat(&fileName[0], &filePath[pathPosPtr+1]);			break;		}	}}////////////////////////////////////////////////////////////////////////////////////////////	Name:	GetExtensionFromPath()//	Params:	N/A//	Desc:	This function is used to extract the file extension//////////////////////////////////////////////////////////////////////////////////////////void file::GetExtensionFromPath(){	unsigned long	lengthOfPath	=	0;	unsigned long	pathPosPtr		=	0;	lengthOfPath = strlen(&filePath[0]);	fileExt[0] = NULL;	for (	pathPosPtr = (lengthOfPath - 1); 			pathPosPtr >= 0; 			pathPosPtr--)	{		if ( filePath[pathPosPtr] == '.')		{			strcat(&fileExt[0], &filePath[pathPosPtr+1]);			break;		}	}}////////////////////////////////////////////////////////////////////////////////////////////	Name:	DetermineFileSize()//	Params:	N/A//	Desc:	This function is used to get the file size of the file.//////////////////////////////////////////////////////////////////////////////////////////void file::DetermineFileSize(){	fseek(fp, 0, SEEK_END);	fileSize = ftell(fp);}


I added another contructor:

file();

and that seemed to solve the problem.

Is that what i should have done?

ace
A better solution would have been to use a pointer to your file objects as the type when creating your list object, since your list class doesn't handle object copying or deletion properly in it's node manipulation routines.

Is there any reason that you aren't using the standard classes for this?
Basically because i want to doit mysefl. There is far to much that is done for programmers and i want to become a very good one. So im learning this way.

If STL etc is so easy to use it wont be a problem for me when im done here.

ace

This topic is closed to new replies.

Advertisement