• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 412
  • Last Modified:

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

0
brich744
Asked:
brich744
2 Solutions
 
jkrCommented:
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.
0
 
evilrixSenior Software Engineer (Avast)Commented:
My article "Separating C++ template declaration and implementation" explains in detail why you are having problems and explains how to resolve them.
0
 
phoffricCommented:
See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 and following sections if interested.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
phoffricCommented:
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.
0
 
sarabandeCommented:
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
0
 
Todd GerbertIT ConsultantCommented:
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.
0
 
Todd GerbertIT ConsultantCommented:
@evilrix

I guess I should have read your article first - that was much more useful than the cplusplus.com tutorial page.
0
 
phoffricCommented:
@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.
0
 
Todd GerbertIT ConsultantCommented:
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. ;)
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now