Undefined Reference " " Error

So I am writing code for an elevator program. Using templated Stack and Queue classes. I have an exectuive class and implementation file that uses the methods from the Stack and Queue classes with a main file that just calls Executive.

I know my code isn't finished and I have pretty sloppy formatting, but I'm getting a compiler error and it is making it impossible for me to move on.

Basically when I call the Stack and Queue methods in Executive I get this error:
1
2
Executive.o: In function `Executive::run(char*)':
/home//EECS_268/Executive.cpp:35: undefined reference to `Queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::enqueue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'

I get this error for all my methods in Queue and Stack as well as this

 
Executive.o:(.rodata._ZTV5QueueINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE[_ZTV5QueueINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEE]+0x28): undefined reference to `Queue<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::enqueue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' 


My first question, which I dont think is the problem but I'm not sure, is do I need to have my implementations finished to call them? (I wouldn't think having a blank implementation would cause this problem)

If not, here is the rest of my code and my makefile:

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
//main.cpp

#include "Executive.h"
using namespace std;

int main(int argc, char* argv[])
{

	Executive Exec(argv[1]);
	Exec.run();

	return(0);
}


Executive.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Executive.h

#ifndef EXECUTIVE_H
#define EXECUTIVE_H

#include "Stack.h"
#include "Queue.h"


class Executive
{
	public:
	void run(char* fileName);

};
#endif 


Exectuive.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//Executive.cpp - 

#include "Executive.h"
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace std;

void Executive::run(char* fileName)
{
	ifstream iFile(fileName);

	string line;
	string tmp;


	Stack<string> myStack;
	Queue<string> myQueue;

	string name;
	int num = 0;

	while(getline(iFile, line))
	{
	stringstream ss(line);
	ss>>tmp;


	try{

		if(tmp == "WAIT")
		{
			ss>>name;
			myQueue.enqueue(name);
		}
		else if(tmp == "PICK_UP")
		{
			
			myStack.push(myQueue.peekFront() /*const*/);
			myQueue.dequeue();
		}
		else if(tmp == "INSPECTION")
		{
			cout<<"Elevator Status:\n";

			if(myStack.isEmpty() /*const*/ == true)
			{
				cout<<"The elevator is empty\n";
			}
			else
			{
				cout<<"The elevator is not empty\n";
			}
		
			cout<<myStack.peek() /*const*/<<" will be the next person to leave the elevator.\n";
			cout<<myQueue.peekFront() /*const*/<<" will be the next person to get on the elevator\n";
		}
		else if(tmp == "DROP_OFF")
		{
			ss>>num;

			for(int i = 0; i<num; i++)
			{
				myStack.pop();
			}
		}
		else
		{
			cout<<"error, invalid request\n";
		}
		
}

			catch(exception& e)
			{
			cout<<e.what();
			}


}


}


Queue.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Queue.h - 

#ifndef QUEUE_H
#define QUEUE_H

#include "QueueInterface.h"

template <typename T>
class Queue:public QueueInterface<T>
{

	public:

	 ~Queue() {};

	//returns true if the queue is empty, false otherwise
	 bool isEmpty() const;

	//Entry added back to the queue
	 void enqueue(const T value);

	//assumes the queue is not empty	
	//front of the front is removed
	//throws PVE if attempted on empty queue, doesnt return value in this case
	 void dequeue() throw(PreconditionViolationException);

	//assumes the queue is not empty
	//returns the value at the front of the stack
	// throws PVE if attempted on empty queue, doesnt return value in this case.
	 T peekFront() const throw(PreconditionViolationException);


};
#endif 


Queue.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//Queue.cpp - 

#include "Queue.h"
using namespace std;

Queue::~Queue()
{
}

bool Queue::isEmpty();
{
}

void enqueue(const T value)
{
}

void dequeue() throw(PreconditionViolationException)
{
}

T peekFront() const throw(PreconditionViolationException)
{
}


QueueInterface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//QueueInterface.h - 

#ifndef QUEUE_INTERFACE_H
#define QUEUE_INTERFACE_H

//#include "PreconditionViolationException.h"

template <typename T>
class QueueInterface
{

	public:

	virtual ~QueueInterface() {};

	//returns true if the stack is empty, false otherwise
	virtual bool isEmpty() const = 0;

	//Entry added back to the queue
	virtual void enqueue(const T value) = 0;

	//assumes the queue is not empty	
	//front of the front is removed
	//throws PVE if attempted on empty queue, doesnt return value in this case
	virtual void dequeue() throw(PreconditionViolationException) = 0;

	//assumes the queue is not empty
	//returns the value at the front of the stack
	// throws PVE if attempted on empty queue, doesnt return value in this case.
	virtual T peekFront() const throw(PreconditionViolationException) = 0;


};
#endif 


StackInterface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//StackInterface.h - 

#ifndef STACK_INTERFACE_H
#define STACK_INTERFACE_H

#include "PreconditionViolationException.h"

template <typename T>
class StackInterface
{
	public:
	virtual ~StackInterface() {};
	
	//returns true if the stack is empty, false otherwise
	virtual bool isEmpty() const = 0;
	
	//Entry added to top of stack
	//Thrown PreconditionViolationException if push cannot occur (e.g. stack full)
	virtual void push(const T value) throw(PreconditionViolationException) = 0;

	//assumes the stack is not empty
	//top of stack uis removed
	//throws PVE whena  pop is attempted on an empty stack. Does not return a value in this case
	virtual void pop() throw(PreconditionViolationException) = 0;

	//assumes stack is not empty
	//returns the value at top of stack
	//throws a PVE is attempted on an empty stack, doesnt return value in this case
	virtual T peek() const throw(PreconditionViolationException) = 0;




};
#endif 


Stack.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//Stack.h

#ifndef STACK_H
#define STACK_H

#include "StackInterface.h"

template <typename T>
class Stack:public StackInterface<T>
{

	public:

	 ~Stack() {};
	

	//returns true if the stack is empty, false otherwise
	 bool isEmpty() const;
	
	//pre:
	//post:
	//Entry added to top of stack
	//Thrown PreconditionViolationException if push cannot occur (e.g. stack full)
	 void push(const T value) throw(PreconditionViolationException);

	//assumes the stack is not empty
	//top of stack uis removed
	//throws PVE whena  pop is attempted on an empty stack. Does not return a value in this case
	 void pop() throw(PreconditionViolationException);

	//assumes stack is not empty
	//returns the value at top of stack
	//throws a PVE is attempted on an empty stack, doesnt return value in this case
	 T peek() const throw(PreconditionViolationException);

	private:
	int *p;
	int top, legnth;


};
#endif 


Stack.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//Stack.cpp - 

#include "Stack.h"
using namespace std;

Stack::~Stack()
{
delete[]
}

bool Stack::isEmpty();
{
	
}

void Stack::push(const T value) throw(PreconditionViolationException)
{
if(p==0)
{
	cout<<"stack of zero size\n";
}
else if(top==(length-1))
{
	cout<<"\nCannot push "<< value<<" stack full";
}
else
{
	top++;
	p[top]=value;
}

void Stack::pop() throw(PreconditionViolationException)
{


}

T Stack::peek() const throw(PreconditionViolationException)
{


}


Lastly,

makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ElevatorAction: main.o Executive.o
	g++ -std=c++11 -g -Wall main.o Executive.o -o Elevator

main.o: main.cpp QueueInterface.h StackInterface.h Queue.h Queue.cpp Stack.h Stack.cpp 
	g++ -std=c++11 -g -Wall -c main.cpp

Executive.o: Executive.h Executive.cpp  
	g++ -std=c++11 -g -Wall -c Executive.cpp

PreconditionViolationException.o: PreconditionViolationException.h PreconditionViolationException.cpp
	g++ -std=c++11 -g -Wall -c PreconditionViolationException.cpp

Queue.o: Queue.h Queue.cpp 
	g++ -std=c++11 -g -Wall -c Queue.cpp

Stack.o: Stack.h Stack.cpp 
	g++ -std=c++11 -g -Wall -c Stack.cpp


clean:
	rm *.o ElevatorAction


compiling with c++11 g++

I have a feeling something is wrong with my makefile but I'm not quite sure.
Any help/input would be greatly appreciated especially with the Undefinded Reference Error.
Thanks in advanced.
The definitions for member functions of template classes should be in the header files, not in .cpp files.
I never really understood why that a template class should be in a/the header file.

Is that enforce by the compiler?

Also, does that fix the code?

Imma going to bookmark this conversation. It seems interesting.
A template class is ignored by the compiler unless you use it with its template parameter. Since the .cpp is not included at that particular time the definitions of this .cpp cannot be fetched by the compiler (the compiler does not know where to find the definitions).
So, do I still need to keep the .cpp file but also define the methods in the template class?
Im still just confused how to fix the problem (what stays/what gets deleted)
So, do I still need to keep the .cpp file but also define the methods in the template class?

No. Define the methods in the header file. Get rid of the corresponding .cpp file.
Awesome!

Taking out the .cpp files and moving the definitions into the header files seems to have fixed my undefined reference error.

Thanks for the help all!
Topic archived. No new replies allowed.