0

I am creating my own stack and queues by using vectors, lists and dynamic arrays.

I have the following header files for my stack and queue:

miniStack.h

#ifndef MINISTACK_H
#define MINISTACK_H

#include <vector>
#include <list>

using namespace std;

 template <typename T>
 class miniStackVT {
 private:
    vector<T> content;
    int elementCount;
 public:
    miniStackVT();
    ~miniStackVT();
    int size() const;
    bool IsEmpty() const;
    void Push(const T& item);
    void PrintStack();
    void Pop();
    T& TopStack();
};

template <typename T>
class miniStackLT {
private:
    list<T> content;
    int elementCount;
public:
    miniStackLT();
    ~miniStackLT();
    int size() const;
    bool IsEmpty() const;
    void Push(const T& item);
    void PrintStack();
    void Pop();
    T& TopStack();
};

template <typename T>
class miniStackDA {
private:
    T* content;
    int elementCount;
    void reserve(int n, bool copy);
    int arrSize;
public:
    miniStackDA();
    ~miniStackDA();
    int size();
    bool IsEmpty();
    void Push(const T& item);
    void PrintStack();
    void Pop();
    T& TopStack();
};

#endif

miniQueue.h

#ifndef MINIQUEUE_H
#define MINIQUEUE_H

#include <vector>
#include <list>

using namespace std;

 template <typename T>
 class miniQueueVT {
 private:
    vector<T> content;
    int elementCount;
 public:
    miniQueueVT();
    ~miniQueueVT();
    void enqueue(const T&);
    void dequeue();
    T& front();
    void PrintQueue() const;
    bool IsEmpty();
    int size();
}; 

template <typename T>
class miniQueueLT {
private:
    list<T> content;
    int elementCount;
public:
    miniQueueLT();
    ~miniQueueLT();
    void enqueue(const T&);
    void dequeue();
    T& front();
    void PrintQueue();
    bool IsEmpty();
    int size();
}; 

template <typename T>
class miniQueueDA {
private:
    T *content;
    int elementCount;
    void reserve(int n, bool copy);
    int arrSize;
public:
    miniQueueDA();
    ~miniQueueDA();
    void enqueue(const T&);
    void dequeue();
    T& front();
    void PrintQueue();
    bool IsEmpty();
    int size();
};

#endif

Here are my .cpp files related to both of my header files:

miniStack.cpp:

#include "miniStack.h"
#include <vector>
#include <list>
#include <iostream>


//VECTOR MEMBER FUNCTIONS
template <typename T>
miniStackVT<T>::miniStackVT() {
    elementCount = 0;
    content.resize(0);
} 


 template <typename T>
 int miniStackVT<T>::size() const{
    return content.size();
 }

 template <typename T>
 bool miniStackVT<T>::IsEmpty() const{
    return content.empty();
 }

 template <typename T>
 void miniStackVT<T>::Push(const T& item) {
    content.push_back(item);
    elementCount++;
}

 template <typename T>
 void miniStackVT<T>::PrintStack() {
    for(int i = elementCount - 1; i >= 0; i--) {
         cout << content[i] << " | ";
    }
}

template <typename T>
void miniStackVT<T>::Pop() {
    content.pop_back();
    elementCount--;
}

template <typename T>
T& miniStackVT<T>::TopStack() {
    return content.back();
}

//LIST MEMBER FUNCTIONS
template <typename T>
miniStackLT<T>::miniStackLT() {
    elementCount = 0;
    content.resize(0);
}

template <typename T>
miniStackLT<T>::~miniStackLT() {

}

template <typename T>
int miniStackLT<T>::size() const{
    return content.size();
}

template <typename T>
bool miniStackLT<T>::IsEmpty() const{
    return content.empty();
} 

template <typename T>
void miniStackLT<T>::Push(const T& item) {
    content.push_back(item);
    elementCount++;
} 

template <typename T>
void miniStackLT<T>::PrintStack() {
    list<T>::iterator rit;
    for (auto rit = content.rbegin(); rit != content.rend(); ++rit) {
        cout << *rit << " | ";
    }
} 

template <typename T>
void miniStackLT<T>::Pop() {
    content.pop_back();
    elementCount--;
}


//DARRAY DATA MEMBERS
template <typename T>
miniStackDA<T>::miniStackDA() {
    arrSize = 50;
    content = new T[arrSize];
    elementCount = 0;
}

template <typename T>
miniStackDA<T>::~miniStackDA() {
    delete[] content;
}

template <typename T>
int miniStackDA<T>::size() {
    return elementCount;
} 

template <typename T>
bool miniStackDA<T>::IsEmpty() {
    if (elementCount == 0)
        return true;
    else return false;
}

template <typename T>
void miniStackDA<T>::Push(const T& item) {
    if (elementCount < arrSize) {
        content[elementCount] = item;
        elementCount++;
    }
    else {
        reserve(arrSize * 2, true);
        content[elementCount] = item;
        elementCount++;
    }
} 

template <typename T>
void miniStackDA<T>::reserve(int n, bool copy) {
    T *newArr;
    int i;

    newArr = new T[n];

    if (copy)
        for (i = 0; i < elementCount; i++)
            newArr[i] = content[i];

    if (content != NULL)
        delete[] content;

    content = newArr;
    elementCount = n;
}

template <typename T>
void miniStackDA<T>::PrintStack() {
    for (int i = elementCount - 1; i >= 0; i--) {
        cout << content[i] << " | ";
    }
} 

template <typename T>
void miniStackDA<T>::Pop() {
    elementCount--;
}

template <typename T>
T& miniStackDA<T>::TopStack() {
    return content[elementCount - 1];
} 

miniQueue.cpp:

#include "miniQueue.h"
#include "iostream"
#include <vector>
#include <list>

using namespace std;

//START VECTOR MEMBER FUNCTIONS

template <typename T>
miniQueueVT<T>::miniQueueVT() {
    elementCount = 0;
    content.resize(0);
}

template <typename T>
miniQueueVT<T>::~miniQueueVT() {

}

template <typename T>
void miniQueueVT<T>::enqueue(const T& item) {
    content.push_back(item);
    elementCount++;
}

template <typename T>
void miniQueueVT<T>::dequeue() {
    content.pop_back();
    elementCount--;
}

template <typename T>
T& miniQueueVT<T>::front() {
    return content.front();
}

template <typename T>
void miniQueueVT<T>::PrintQueue() const {
    for (int i = elementCount - 1; i >= 0; i--) {
        cout << content[i] << " | ";
    }
}

template <typename T>
bool miniQueueVT<T>::IsEmpty() {
    return content.empty();
}

template <typename T>
int miniQueueVT<T>::size() {
    return elementCount;
}

//START LIST MEMBER FUNCTIONS

template <typename T>
miniQueueLT<T>::miniQueueLT() {
    elementCount = 0;
    content.resize(0);
}

template <typename T>
miniQueueLT<T>::~miniQueueLT() {

}

template <typename T>
void miniQueueLT<T>::enqueue(const T& item) {
    content.push_back(item);
    elementCount++;
}


template <typename T>
void miniQueueLT<T>::dequeue() {
    content.pop_front();
    elementCount--;
} 

template <typename T>
T& miniQueueLT<T>::front() {
    return content.front();
}

template <typename T>
void miniQueueLT<T>::PrintQueue() {
    list<T>::iterator iter;
    for (iter = content.begin(); iter != content.end(); iter++) {
        cout << *iter << " | ";
    }
}

template <typename T>
bool miniQueueLT<T>::IsEmpty() {
    return content.empty();
}

template <typename T>
int miniQueueLT<T>::size() {
    return content.size();
}


//START DYNAMIC ARRAY MEMBER FUNCTIONS

template <typename T>
miniQueueDA<T>::miniQueueDA() {
    arrSize = 50;
    content = new T[arrSize];
    elementCount = 0;
}

template <typename T>
miniQueueDA<T>::~miniQueueDA() {

}

template <typename T>
void miniQueueDA<T>::enqueue(const T& item) {
    if (elementCount < arrSize) {
        content[elementCount] = item;
    }
    else {
        reserve(arrSize * 2, true);
        content[elementCount] = item;
        elementCount++;
    }
}


template <typename T>
void miniQueueDA<T>::dequeue() {
     elementCount--;
}

template <typename T>
void miniQueueDA<T>::reserve(int n, bool copy) {
    T *newArr;
    int i;

    newArr = new T[n];

    if (copy) {
        for (i = 0; i < elementCount; i++) {
            newArr[i] = content[i];
        }
    }
    if (content != NULL)
        delete[] content;

    content = newArr;
    elementCount = n;
}


template <typename T>
T& miniQueueDA<T>::front() {
    return content[0];
}

template <typename T>
bool miniQueueDA<T>::IsEmpty() {
    if (elementCount == 0)
        return true;
    else return false;
}

template <typename T>
int miniQueueDA<T>::size() {
    return elementCount;
}
template <typename T>
void miniQueueDA<T>::PrintQueue() {
    for (int i = elementCount - 1; i >= 0; i--) {
        cout << content[i] << " | ";
    }
}

I'm getting the following errors when I go to compile the program:

Error   LNK2019 unresolved external symbol "public: __thiscall    miniStackVT<int>::~miniStackVT<int>(void)" (??1?$miniStackVT@H@@QAE@XZ) referenced in function "void __cdecl StackVTMenu<int>(class miniStackVT<int>)" (??$StackVTMenu@H@@YAXV?$miniStackVT@H@@@Z)    Project 2   E:\Project 2\Project 2\Driver.obj   1
Error   LNK2019 unresolved external symbol "public: int & __thiscall miniStackLT<int>::TopStack(void)" (?TopStack@?$miniStackLT@H@@QAEAAHXZ) referenced in function "void __cdecl StackLTMenu<int>(class miniStackLT<int>)" (??$StackLTMenu@H@@YAXV?$miniStackLT@H@@@Z) Project 2   E:\Project 2\Project 2\Driver.obj   1
Error   LNK1120 2 unresolved externals  Project 2   E:\Project 2\Debug\Project 2.exe    1

I have tried changing around which files are included in the main and the .h files. Right now i haveminiStack.cpp and miniQueue.cpp included in the main.

Any help would be greatly appreciated.

Zack Sloan
  • 133
  • 1
  • 1
  • 8

1 Answers1

0

If you use templates in C++, your header file must contain implementations. If you only implement in your source files the compiler will compile each file and will link later.

But this cannot work in the case of templates since the compiler has to observe the generic type by checking its concrete usage.

dtell
  • 2,488
  • 1
  • 14
  • 29
  • So i should put all of my implementations in my 2 header files? – Zack Sloan Apr 03 '17 at 15:49
  • That depends if you need all of them. Include everything where a generic type T has a concrete usage and the compiler has to observe it to replace T with the concrete type. EDIT: With include I mean put in your header, not include in preprocessor `#include` context – dtell Apr 03 '17 at 15:50
  • Will try that in a few – Zack Sloan Apr 03 '17 at 15:57