Okay, I know what's wrong with my program but I don't know what to do to fix it.

I have to take a program we previous made and make it a template class. Okay, sounds easy enough. I know all the writing it right cause it ran fine before, now the problem is the stupid ItemType in my struct and (possibly) one later in my main.

Excluding all the code in between which can be corrected once I know the answer, this is the section code I'm focusing on.

typedef NodeType* NodePtr;

struct NodeType
{
    ItemType item;
    NodePtr  next;
};
template<class ItemType>
List<ItemType>::~List()
// Post: All the components are deleted.
{
    NodeType* tempPtr;

	while (listPtr != NULL)
	{
		tempPtr = listPtr;
		listPtr = listPtr->next;
		delete tempPtr;
	}
}

int main ()
{   List<int> a;
    ItemType element;
    ifstream InData;
    InData.open ("int.dat");
	if (InData.is_open())
           { while (InData >> element)
                   { a.Insert(element); }
           }
...
return 0;
}

I need struct "ItemType item" to be affected by my template <class ItemType> so that it changes to whatever value is needed and for the main "ItemType element" to be affected by it as well (not sure if this is possible, but I'm asking anyway).

So, how do I do that and how does it affect the other pieces of code that use my struct NodeType?

I know I need to put the <class ItemType> in front of the struct like I did later in the destructor, but what else is needed besides that piece. That's really what has me puzzled.

Recommended Answers

All 2 Replies

You can't make a typedef out of an incomplete type, so the following would be illegal if NodeType is generalized--

typedef NodeType* NodePtr;

struct NodeType
{
    ItemType item;
    NodePtr  next;
};

-- because templates of typedefs are illegal.

You would need to alter your struct to have a variable type, like such--

template<class ItemType>
struct NodeType{

    ItemType* item;
    NodeType* next;

};

--if your Node is declared outside of your List class.

If its outside your list class and you want to create NodeTypes that hold the same type as the list, you'll have to do something like this--

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

template<class ItemType>struct NodeType;
template<class ItemType>struct List;

template<> // specialization for chars
struct NodeType<char>{
	char item;
	NodeType *next;
	NodeType(char);
};

NodeType<char>::NodeType(char myItem) : next(0){
	item = myItem;
}


template<> // specialization for chars
struct List<char>{

	NodeType<char> *root;
	List();
	void add(char);
	void viewAll();
};

List<char>::List() : root(0){}

void List<char>::add(char val){
	if(root == NULL){
		root = new NodeType<char>(val);
	}else{
		NodeType<char> *temp = root;

		while(temp->next != NULL)temp = temp->next;

		temp->next = new NodeType<char>(val);
	}
}

void List<char>::viewAll(){

	NodeType<char> *temp = root;
	while(temp != NULL){
		cout << temp->item << endl;
		temp = temp->next;
	}
}


template<class ItemType> // generalized for all other types
struct NodeType{
	ItemType *item; // ptr to prevent "slicing", see Stanley B. Lippman's 'The C++ Object Model' for a thorough explanation
	NodeType *next;
	NodeType(ItemType&);
};

template<class ItemType>
NodeType<ItemType>::NodeType(ItemType& myItem) : next(0) {
	item = &myItem;
}

template<class ItemType> // generalized  for all other types
struct List{

	NodeType<ItemType> *root;
	List();
	void add(ItemType&);
};

template<class ItemType>
List<ItemType>::List() : root(0){}

template<class ItemType>
void List<ItemType>::add(ItemType& val){
	if(root == NULL){
		root = new NodeType<ItemType>(val);
	}else{
		NodeType<ItemType> *temp = root;

		while(temp->next != NULL)temp = temp->next;

		temp->next = new NodeType<ItemType>(val);
	}
}

class MyObject{
	public:
		const char *name;
		MyObject(const char*);
};

MyObject::MyObject(const char * theName) : name(theName) {}

/**
 * Object deletion ignored since OP has it defined**
 */

int main(){

	MyObject myName = "Alex Edwards";

	List<MyObject> myList; // invoking generalized List constructor

	myList.add(myName);

	cout << myList.root->item->name << endl;

	List<char> myOtherList; // specialized List for chars

	myOtherList.add('a');
	myOtherList.add('b');
	myOtherList.add('c');

	myOtherList.viewAll();

	int x = 0;
	int y = 1;
	int z = 2;

	List<int> intList; // not specialized - treated like generalized type

	intList.add(x);
	intList.add(y);
	intList.add(z);

	cin.ignore();
	cin.get();
	return 0;
}

--Note that there are two definitions for List and Node. This is because templates of different types can have different definitions.

I'd like to apologize...

the previous example can be forgiven for not implementing Node deletion (since OP has it defined), but can't be forgiven for forgetting appropriate Node declarations in global scope of NodeType structs (in both classes).

This is a corrected version--

#include <iostream>

using std::cout;
using std::cin;
using std::endl;

template<class ItemType>struct NodeType;
template<class ItemType>struct List;

template<> // specialization for chars
struct NodeType<char>{
	char item;
	NodeType<char> *next;
	NodeType(char);
};

NodeType<char>::NodeType(char myItem) : next(0){
	item = myItem;
}


template<> // specialization for chars
struct List<char>{

	NodeType<char> *root;
	List();
	void add(char);
	void viewAll();
};

List<char>::List() : root(0){}

void List<char>::add(char val){
	if(root == NULL){
		root = new NodeType<char>(val);
	}else{
		NodeType<char> *temp = root;

		while(temp->next != NULL)temp = temp->next;

		temp->next = new NodeType<char>(val);
	}
}

void List<char>::viewAll(){

	NodeType<char> *temp = root;
	while(temp != NULL){
		cout << temp->item << endl;
		temp = temp->next;
	}
}


template<class ItemType> // generalized for all other types
struct NodeType{
	ItemType *item; // ptr to prevent "slicing", see Stanley B. Lippman's 'The C++ Object Model' for a thorough explanation
	NodeType<ItemType> *next;
	NodeType(ItemType&);
};

template<class ItemType>
NodeType<ItemType>::NodeType(ItemType& myItem) : next(0) {
	item = &myItem;
}

template<class ItemType> // generalized  for all other types
struct List{

	NodeType<ItemType> *root;
	List();
	void add(ItemType&);
};

template<class ItemType>
List<ItemType>::List() : root(0){}

template<class ItemType>
void List<ItemType>::add(ItemType& val){
	if(root == NULL){
		root = new NodeType<ItemType>(val);
	}else{
		NodeType<ItemType> *temp = root;

		while(temp->next != NULL)temp = temp->next;

		temp->next = new NodeType<ItemType>(val);
	}
}

class MyObject{
	public:
		const char *name;
		MyObject(const char*);
};

MyObject::MyObject(const char * theName) : name(theName) {}

/**
 * Object deletion ignored since OP has it defined**
 */

int main(){

	MyObject myName = "Alex Edwards";

	List<MyObject> myList; // invoking generalized List constructor

	myList.add(myName);

	cout << myList.root->item->name << endl;

	List<char> myOtherList; // specialized List for chars

	myOtherList.add('a');
	myOtherList.add('b');
	myOtherList.add('c');

	myOtherList.viewAll();

	int x = 0;
	int y = 1;
	int z = 2;

	List<int> intList; // not specialized - treated like generalized type

	intList.add(x);
	intList.add(y);
	intList.add(z);

	cin.ignore();
	cin.get();
	return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.