the interface of Stack.h
#include "stdafx.h"
//use linkedlist to implement the stack
//which is different from using the array to implement the stack
#ifndef STACK_H
#define STACK_H
using namespace std;
namespace stackNameSpace {
template<class T>
struct StackNode {
T value;
T min_value; //current local min value
StackNode* next;
};
typedef StackNode<class T>* StackNodePtr;
template<class T>
class Stack {
private:
StackNodePtr top;
public:
Stack();
Stack(const Stack& a_stack);
~Stack();
bool empty() const;
T pop();
void push(T the_value);
T getMin();
};
} //end of namespace
#endif
The implementation of the stack.h
#include "stdafx.h"
//use linkedlist to implement the stack
//which is different from using the array to implement the stack
#ifndef STACK_CPP
#define STACK_CPP
#include <iostream>
#include <cstdlib>
#include "Stack.h"
using namespace std;
namespace stackNameSpace {
template<class T>
Stack<T>::Stack() : top(NULL) //here should be Stack<T> instead of Stack
{}
template<class T>
Stack<T>::Stack(const Stack& a_stack) {
if (a_stack.top == NULL) {
return NULL;
}
else {
StackNodePtr currentOld = a_stack.top;
//construct the top of the new stack
StackNodePtr currentNew = new StackNode<class T>;//the struct
currentNew->value = currentOld->value;
currentNew->min_value = currentOld->min_value;
top = currentNew;
//contruct the rest node in the stack
currentOld = currentOld->next;
while (currentOld != NULL) {
currentNew->next = new StackNode<class T>;
currentNew = currentNew->next;
currentNew->value = currentOld->value;
currentNew->min_value = currentOld->min_value;
currentOld = currentOld->next;
}
currentOld->next = NULL;
}
}
template<class T>
Stack<T>::~Stack() {
T data;
while (!empty()) {
data = pop();
}
}
template<class T>
bool Stack<T>::empty() const {
return (top == NULL);
}
template<class T>
T Stack<T>::pop() {
if (empty()) {
cout << "Error: popping an empty stack.\n";
exit(1);
}
T result = top->value;
StackNodePtr temp = new StackNode<class T>;
temp = top;
top = top->next;
delete temp;
return result;
}
template<class T>
void push(T the_value) {
StackNodePtr temp = new StackNode<class T>;
temp->value = the_value;
temp->min_value = min(the_value, getMin());//This is Much better
//temp->min_value = top->min_value; //This is NOT secure, since top may be NULL
temp->next = top; //update the top node
top = temp;
}
template<class T>
T getMin() {
if (top == NULL)
return INT_MAX;
else {
return top->min_value;
}
}
} //end of namespace
#endif
The function using the Stack class
#include "stdafx.h"
#include <iostream>
#include "Stack.h" //this is not the <stack>, which is STL
//using namespace std; //NOTE: this must be wrong! because can not use multiple namespace at the same time
using namespace stackNameSpace;
using std::cout;
using std::endl;
int main() {
Stack<int> sWithMin;
sWithMin.push(5);
cout<< sWithMin.getMin() << endl;
sWithMin.push(4);
cout<< sWithMin.getMin() << endl;
sWithMin.push(5);
cout<< sWithMin.getMin() << endl;
sWithMin.push(3);
cout<< sWithMin.getMin() << endl;
sWithMin.push(6);
cout<< sWithMin.getMin() << endl;
return 0;
}
When I compile the project, I get an error in main() that "error C2079: 'stackNameSpace::StackNode::value' uses undefined class 'stackNameSpace::T'"
I can not figure out the reason why it has the error. Could anyone please help me?
namespace stackNameSpace {
template<class T>
struct StackNode {
T value;
T min_value; //current local min value
StackNode* next;
};
So StackNode is a template that depends on a type parameter T.
typedef StackNode<class T>* StackNodePtr;
This is not part of a template definition and class T refers to a class named T.
(Actually class T always refers to a class named T, except in the construct template <class T>, which could be replaced by template <typename T>. With a template definition with type parameter T that type must be referred to using plain T, not class T.)
As you haven't declared a class named T yet, the StackNodePtr definition implicitly declares an incomplete class type at surrounding namespace scope (i.e the incomplete class type is ::stackNameSpace::T).
template<class T>
class Stack {
private:
StackNodePtr top;
Now here StackNodePtr is not dependent on the template parameter T. Instead it is a pointer to a fixed type StackNode<::stackNameSpace::T> and top->value will be of incomplete type class T unrelated to the template parameter of Stack.
If you use a Stack<int> and instantiate anything using top->value within such a stack, you'll see the error you show.
BTW: another, unrelated issue is that definitions of templates (including member functions of class templates) must be visible at the point where a template is instantiated. Typically that means that you should not put template member definition into a cppfile which is compiled separately. Instead they should be in a header file that is included wherever the template is used.
While JoergB correctly pointed out the issue with the code that you posted, I would like to throw some light on what he was explaining in the last part of his answer.
When using templates in Visual studio I would make sure that the header and implementation of the class come under a single compilation unit. Try renaming Stack.cpp to Stack.inl and include it at the end of Stack.h
void push(T the_value);
T getMin();
};
} //end of namespace
#include "Stack.inl"
#endif
Be sure to exclude Stack.inl from build. Right click on it in the Solution Explorer > Properties > Exclude from build > Yes.
Related
stack.h
template <class DataType>
class Stack {
private:
int * topPtr;
public:
Stack(); //constructor; initializes top to nullptr
void push(); //adds a node
void pop(); //removes most recently added node
};
And stack.cpp thus far:
#include "stack.h"
//using namespace std;
template <class DataType>
Stack::Stack() {
topPtr = nullptr;
}
It is the Stack:: that is underlined with the error "name followed by :: must be a class or namespace." If relevant, I am using VS Code.
I would just like to have a generic stack implementation, and I'm not sure why I'm getting this error? Thanks!
Syntax of out of class definition is:
template <class DataType>
Stack<DataType>::Stack() : topPtr{nullptr} {}
// ^^^^^^^^
This problem occurs in my main.cpp:
using namespace std;
#include <iostream>
#include "BST.h"
#include "Packet.h"
int main()
{
BST test; // It occurs on this line!
Packet one(1, "testPacket", 1, 1);
system("Pause");
}
The error on that line says:
argument list for class template "BST" is missing
I don't know how to fix it. I just want to initialize the BST. How can I fix this error? I'm not very experienced with templates. Please help. My priority is fixing this glaring problem right now. Can I get help?
For reference purposes:
BST.h:
#ifndef BST_H
#define BST_H
using namespace std;
template <typename T>
class Node {
public:
Node() : rlink(nullptr), llink(nullptr) {}
~Node() {}
private:
T data;
Node *rlink, *llink;
};
template <typename T>
class BST {
public:
BST();
void insert(T data);
private:
Node * root;
};
#endif
BST.cpp
#include "BST.h"
template <typename T>
BST<T>::BST() : root(nullptr) {}
template <typename T>
void BST<T>::insert(T data) {
if (root != nullptr) {
}
else {
cout << "NPTR" << endl;
}
}
Packet.h
#ifndef PACKET_H
#define PACKET_H
#include <string>
using namespace std;
class Packet {
public:
Packet(int partId, string description, double price, int partCount) :
partId(partId), description(description), price(price), partCount(partCount) {}
int getPartId() const { return partId; }
string getDescription() const { return description; }
double getPrice() const { return price; }
int getPartCount() const { return partCount; }
private:
int partId;
string description;
double price;
int partCount;
};
#endif
There are 2 problems.
The first is that Node needs to know what type T is, so you need to tell it when you use Node like this:
template <typename T>
class BST {
public:
BST();
void insert(T data);
private:
Node<T> * root;
};
Secondly, BST needs to know what its own type T is when you try to use it, so you need to do it like this:
BST<int> test; // Or whatever you are searching for in your tree. Doesn't have to be an int
P.S. Just heading this off now, you're probably going to need to implement BST in the header file. Failure to do so might cause linker problems.
P.P.S. I've been reading your comments on the original post, and what you actually probably need this instead:
BST<Packet> test; // Since you are searching for packets.
To start off, I'm kind of new to instantiation files, headers, and source files.
I'm trying to get my code to compile, but I keep hitting a linker error where it says that I'm defining something twice.
I have 6 Files:
- Instantiation.cpp Lab5.cpp Students.cpp Queue.cpp Students.h Queue.h
Instantiation:
#include "Students.cpp"
#include "Lab5.cpp"
#include "Queue.cpp"
template class Queue<int>;
template class QueueNode<int>;
template class Queue < Students* >;
template class QueueNode < Students* >;
Lab5:
#include "Queue.h"
#include "Students.h"
#include <iostream>
using namespace std;
int main(){
Queue <Students*> studentQueue;
Queue <int> integerQueue;
return 0;
}
Students.cpp:
#include "Students.h"
Students::Students(){
}
void Students::printStudent(){
}
Queue.cpp:
#include "Queue.h"
template <class DataType>
Queue<DataType>::Queue(int i){
i = queueSize;
}
template <class DataType>
Queue<DataType>::~Queue(){
}
template <class DataType>
void Queue<DataType>::enQueue(const DataType){
}
template <class DataType>
DataType Queue<DataType>::deQueue(){
return 0;
}
template <class DataType>
DataType Queue<DataType>::topQueue() const {
return 0;
}
template <class DataType>
bool Queue<DataType>::isEmpty() const {
return true;
}
template <class DataType>
bool Queue<DataType>::isFull() const{
return true;
}
Students.h:
#ifndef STUDENTS_H
#define STUDENTS_H
class Students{
public:
char lastName[20];
char firstName[20];
int ID; // ID
Students(); // constr
void printStudent(); // print info
};
#endif
Queue.h:
#ifndef QUEUE_H
#define QUEUE_H
template <class DataType>
class QueueNode {
public:
DataType data;
QueueNode<DataType> *next;
};
template <class DataType>
class Queue {
private:
QueueNode<DataType> *front;
QueueNode<DataType> *back;
int queueSize; // size of a Queue
int queueCnt; // elem count in a Queue
public:
Queue(int = 10); // class constr. - initialize vars
~Queue(); // class destructor - remove all mem space used by queue elems
void enQueue(const DataType); // add item to back of queue
DataType deQueue(); // remove first item from queue and return its value
DataType topQueue() const; // return the value of the first item in the queue
bool isEmpty() const; // returns true if there are no elems in the queue
bool isFull() const; // returns true if no system mem for a new queue node
};
#endif
Here's the output:
http://i.imgur.com/cAPdtKG.png
Please, help.
I don't really get why it thinks I'm defining anything twice.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
I'm trying to create a template c++ Stack, and i'm having some issue with the linker.
I've tried to put all the classes into one cpp file, and it works just fine, but the problem begin once I separate them into different files
here's my classes
main class :
#include <iostream>
#include "stack.h"
using namespace std;
int main()
{
Stack<double>* st = new Stack<double>();
st->push(new Data<double>(10));
cout << st->pop()->getData();
return 0;
}
stack.h :
#ifndef STACK_H
#define STACK_H
#include "data.h"
template <class T>
class Stack
{
public:
Stack():_current(NULL){}
void push(Data<T>* const);
Data<T>* pop();
private:
Data<T>* _current;
};
#endif;
stack.cpp :
#include "stack.h"
template <class T>
Data<T>* Stack<T>::pop()
{
if(this->_current == NULL)
{
cout << "Empty stack." <<endl;
return NULL;
}
else
{
Data<T>* tmpPtr = this->_current;
this->_current = this->_current->getPrev();
return tmpPtr;
}
}
template <class T>
void Stack<T>::push(Data<T>* const data)
{
if(this->_current == NULL) // Empty stack;
{
_current = data;
_current->setPrv(NULL);
}
else
{
Data<T>* tmpPtr = this->_current;
this->_current = data;
this->_current->setPrv(tmpPtr);
}
}
data.h
#ifndef DATA_H
#define DATA_H
template <class T>
class Data
{
public:
Data(T data):_data(data){}
T getData() const { return this->_data; }
void setPrv(Data* const prev){ this->_prev = prev; }
Data* getPrev() const { return this->_prev; }
private:
Data<T>* _prev;
T _data;
};
#endif
Put all the definitions of the template class functions in the .h. They basically aren't allowed to be in separate files.
This occurs becauses templates are not like typical classes. The compiler will generate a class for you off of your template instantiation. Because of this, the compiler will need to know where to lookup the function definitions, so put them inside the .h where the class is defined.
Template functions are not compiled until they're specialized(used), and your stack.cpp doesn't produce any machine code. Move them to stack.h
Hi im working on a program that uses an array of linked lists but im having trouble running it. I keep getting this error and I cannot find a way to fix it. Im only going to include parts of the code that way everything isnt too cluttered. The error message is saying that lines 112 in NodeADT.h, line 141 in MultiListADT.h and line 21 in main.cpp are the ones throwing the error. Ill highlight those lines to make it easier.
Main.cpp
#include <iostream>
#include "MultiListADT.h"
#include <fstream>
#include <string>
using namespace std;
void main(void)
{
MultiListADT<string,100> myList;
string item;
ifstream data;
string input;
int x=0;
data.open("input.txt");
while (!data.eof())
{
getline(data,input);
myList.AddToFront(input); //This is line 21
}
cout << myList << endl;
system("pause");
}
MultiListADT.h
#include <iostream>
#include <fstream>
#include "NodeADT.h"
#include <string>
using namespace std;
template <class TYPE,int threads>
class MultiListADT
{
public:
/** Constructor **/
MultiListADT();
/** Destructor **/
~MultiListADT();
/** Declare accessors (observers) **/
void ResetListForward(int=0);
void ResetListBackward(int=0);
bool IsEmpty(int=0);
int LengthIs(int=0);
bool Search(string, bool=true,int=0);
void GetNextItem(TYPE &,int i=0);
void GetPreviousItem(TYPE &,int=0);
int GetInfo(int=0);
friend ostream& operator << (ostream&, MultiListADT<TYPE, 100>&);
/** Declare mutators (transformers) **/
void MakeEmpty();
void AddToFront(TYPE);
void AddToRear(TYPE);
void InsertInOrder(TYPE);
void Delete(TYPE);
void Sort();
private:
NodeADT<TYPE,threads>* head[threads];
NodeADT<TYPE,threads>* tail[threads];
int length;
string indices[threads];
NodeADT<TYPE,threads>* currentNode[threads];
};
template <class TYPE,int threads>
MultiListADT<TYPE,threads>::MultiListADT()
{
head[threads] = new NodeADT<string,threads>();
tail[threads] = new NodeADT<string,threads>();
head[threads]->setNext(tail[threads]);
tail[threads]->setPrevious(head[threads]);
length = 0;
}
template <class TYPE,int threads>
void MultiListADT<TYPE,threads>::AddToFront(TYPE item)
{
head[0]->AddToFront(item); //This is line 141
length++;
}
NoteADT.h
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int null = 0;
template<class TYPE, int threads>
class MultiListADT;
template <class TYPE, int threads>
class NodeADT
{
public:
NodeADT();
NodeADT(TYPE);
~NodeADT();
TYPE getInfo();
NodeADT<TYPE, threads>* getPrevious(int=0);
NodeADT<TYPE, threads>* getNext(int=0);
void setNext(NodeADT<TYPE, threads>*,int=0);
void setPrevious(NodeADT<TYPE, threads>*,int=0);
bool Search(TYPE, bool=true,int=0);
void AddToFront(TYPE item);
void AddToRear(TYPE item);
void InsertInOrder(TYPE);
bool Delete(TYPE);
friend ostream& operator << (ostream&, MultiListADT<TYPE, threads>&);
private:
TYPE info;
NodeADT<TYPE, threads>* prev[threads];
NodeADT<TYPE, threads>* next[threads];
};
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT()
{
prev[threads] = null;
next[threads] = null;
}
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT(TYPE item)
{
info = item;
prev = null;
next = null;
}
template <class TYPE,int threads>
void NodeADT<TYPE,threads>::AddToFront(TYPE item)
{
NodeADT<TYPE,threads> *temp = new NodeADT<TYPE,threads>;
temp->info = item;
temp->prev[0] = this;
temp->next[0] = next[0];
next[0]->prev[0] = temp; //This is line 112
next[0] = temp;
}
What do YOU think the error means?
On line 112, where do the values for next, prev and temp come from and what are they set to when it crashes? Knowing the values, why do you think it crashed?
Also in one of your NodeADT constructors you assign null to the last element of the array. Or so it appears.
Question: What happens when you assign a value to the element numbered 100 in an array of 100 elements, when element counting starts at 0?
I think the answer, which Zan Lynx has implied, is that you are using threads as an index into your arrays in the constructor of MultiListADT. In AddToFront you use 0 as the index, but that element in the array has never been initialised.