Link to home
Start Free TrialLog in
Avatar of brich744
brich744

asked on

Error with seperating header files from .cpp files

Hello Everyone,

I have a program that has two classes with and both has templates.  The program worked fine when I had everything in the header files. But since I have split the definition and declaration I am receiving multiple errors

PQ.h:

   
#ifndef PQ_H
#define PQ_H

#include<iostream>
#include<vector>
#include<cmath>

using namespace std;

#include"StackLList.h"

template<class Data> class ListNode;

template<class Comparable, class Data>
class PQ
{
public:
	PQ();
	void insert(ListNode<Data>&);
	void delete_max();
	void swap(ListNode<Data>&, ListNode<Data>&);
private:
	vector< ListNode<Data> > vector_PQ;
	int size;
};



#endif

Open in new window


PQ.cpp:

 
#include"PQ.h";


template<class Comparable, class Data>
PQ<Comparable, Data>::PQ()
	:size(0)
{}

template<class Comparable, class Data>
void PQ<Comparable, Data>::insert(ListNode<Data> &x)
{
	if(vector_PQ.size() == 0)
	{
		vector_PQ.push_back(x);
		size++;
		return;
	}
	
		size++;
		vector_PQ.push_back(x);
	int child = size-1;
	int parent = (child/4);

	while(vector_PQ[parent].counter < vector_PQ[child].counter)
	{
		swap(vector_PQ[parent], vector_PQ[child]);
		child = parent;
		parent = (child/4);
	}
}

template<class Comparable, class Data>
void PQ<Comparable, Data>::delete_max()
{

	if(vector_PQ.size() == 1)
	{
		vector_PQ.pop_back();
		return;
	}
	ListNode<Data> nextItem = vector_PQ[0];
	swap(vector_PQ[0], vector_PQ[size-1]);
	size--;

	vector_PQ.pop_back();

	int parent = 0;
	
	vector< ListNode<Data> > child_vec;

	int iter = 1;

	for(int i = 4; i>= 1; i--)
	{
		
		int child = (4*parent)+iter;

		if(child <= vector_PQ.size() - 1)
			vector_PQ[0] = vector_PQ[child];
	
		iter--;

	}	
	
}

template<class Comparable, class Data>
void PQ<Comparable, Data>::swap(ListNode<Data>& a, ListNode<Data>& b)
{
	ListNode<Data> temp;

	temp = a;
	a = b;
	b = temp;
}

Open in new window


StackLList.h
 
#ifndef STACKLLIST_H
#define STACKLLIST_H


#include<iostream>

using namespace std;

#include"PQ.h"

template<class Data>
class ListNode
{

public:
	
	 ListNode(Data &nodeValue, int counter_value)
      : value(nodeValue), next(NULL), counter(counter_value)  
		{}

	 ListNode()
		 :value(NULL),next(NULL), counter(0)
	 {}

	ListNode *next;
	Data value;
	int counter;

};

#endif

Open in new window


StackLList.cpp
 
#include"StackLList.h"

template<class Data, class Comparable>
class StackLList
{
public:
	StackLList();
	~StackLList();
	void push(Data&);
	void pop();
	bool isEmpty();

private:
	
	ListNode<Data> *top;
	PQ<Data, Comparable> *queue;
};

template<class Data, class Comparable>
StackLList<Data, Comparable>::StackLList()
{
	top = NULL;
	queue = new PQ<Data, Comparable>;

}

template<class Data, class Comparable>
StackLList<Data, Comparable>::~StackLList()
{
	ListNode *node_ptr, *next_node;

	node_ptr = top;

	while(node_ptr != NULL)
	{
		next_node = node_ptr->next;
		delete node_ptr;
		node_ptr = next_node;
	}
}

template<class Data, class Comparable>
void StackLList<Data, Comparable>::push(Data& data)
{
	static int timeStamp = 0;
	timeStamp++;

	ListNode<Data> *new_node = new ListNode<Data>(data,timeStamp);

	

	if(isEmpty())
	{
		top = new_node;
		new_node->next = NULL;
	}

	else
	{
		new_node->next = top;
		top = new_node;
	}

	queue->insert(*new_node);

}

template<class Data, class Comparable>
void StackLList<Data, Comparable>::pop()
{
	ListNode<Data> *temp;

	if(isEmpty())
		cout<<"The Stack Is Empty"<<endl;

	else
	{
		
		temp = top;
		delete top;
		top = temp;
	}

	queue->delete_max();

	}

template<class Data, class Comparable>
bool StackLList<Data, Comparable>::isEmpty()
{
	bool flag;

	if(top == NULL)
		flag =true;
	
	else
		flag = false;

	return flag;
}

Open in new window


Main.cpp
#include<iostream>
#include<string>
using namespace std;

#include"StackLList.h"


int main()
{
	cout<<"****************** 4-HEAP PROGRAM *******************"<<endl;

	char number;
	int answer = 1;
	StackLList<char,char> *stack = new StackLList<char,char>;

	
	
	do
	{
		cout<<"1) Push"<<endl;
		cout<<"2) Pop"<<endl;
		cout<<"3) Exit"<<endl;
		cin>>answer;
		
		if(answer == 1)
		{
			cout<<"Please Enter In Your Data"<<endl;
			cin>>number;

				stack->push(number);

		}
		
		else if(answer == 2)
			stack->pop();
		
		else
			break;

	}while(answer != 3);

	system("PAUSE");

	return 0;
}

Open in new window

Avatar of jkr
jkr
Flag of Germany image

In short: While the C++ standard would allow you to do what you did, hardly any compilers support that - as a simple workaround, you could add a

#include "thefile.cpp"

at teh bottom of the headers for your template classes.
ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of phoffric
phoffric

Main.cpp uses StackLList<char,char>, but StackLList class is not defined in StackLList.h.

Your PQ and StackLList are co-dependent (i.e., PQ.h includes StackLList.h and vice-versa). This makes it a bit harder when dealing with templates. It would be easier if these two classes were not coupled.
i would recommend you to go back to your previous header where the implementation of the templates is with the class declaration and so the compiler hasn't problems to instantiate real types with the template as explained in above comments and links.

Sara
Aren't the defintion and declaration of template classes required to be in the same file?


http://www.cplusplus.com/doc/tutorial/templates/:
Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.
@evilrix

I guess I should have read your article first - that was much more useful than the cplusplus.com tutorial page.
@tgerbert,
>> Aren't the defintion and declaration of template classes required to be in the same file?
There are ways to separate template declarations and definitions.
Yup, got that from evilrix's article - I was a little surprised cplusplu.com just outright said "It can't be done" (even if it was just a tutorial), so I gather it's just not commonly done?


@brich744

Sorry I kinda hijacked your thread a bit - I'm done asking questions. ;)