...

/

Understanding the C++ Templates

Understanding the C++ Templates

Learn how the templates work for various data types.

The “empty stack” error in C++

When we attempt to pop an element from an empty stack without proper checking, we might face an error or exception called an “empty stack” error. The following code snippet gives us a more robust stack data structure where we remove all the elements and catch the Stack<>::pop(): empty stack exception message.

Press + to interact
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
using namespace std;
//We will define the Stack<> class and implement generic methods
//to push and pop the elements from the stack
template <class T>
class Stack {
private:
vector<T> elementsToPushAndPop;
public:
void push(T const&);
void pop();
T top() const;
bool empty() const {
return elementsToPushAndPop.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem) {
// we can append the copy of the element that we passed
elementsToPushAndPop.push_back(elem);
}
template <class T>
void Stack<T>::pop () {
// if the stack is empty, we can throw an exception
if (elementsToPushAndPop.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// then we can remove the last element
elementsToPushAndPop.pop_back();
}
template <class T>
T Stack<T>::top () const {
// if the stack is empty, we can throw an exception
if (elementsToPushAndPop.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// then we can return a copy of the last element
return elementsToPushAndPop.back();
}
int main(){
// Let's create a stack of integer elements
Stack<int> stackIntegers;
// now we can keep adding to the stack
stackIntegers.push(500);
stackIntegers.push(501);
cout << stackIntegers.top() << endl;
if(stackIntegers.empty()){
cout << "The stack is empty." << endl;
} else {
cout << "The stack is not empty." << endl;
}
// Let's remove one element from our stack
stackIntegers.pop();
// and see the output
cout << stackIntegers.top() << endl;
// after that we can check whether the stack is empty
if(stackIntegers.empty()){
cout << "The stack is empty." << endl;
} else {
cout << "The stack is not empty." << endl;
}
// and see the output
cout << stackIntegers.top() << endl;
// Let's keep removing the stack elements
try {
// this removes 500
stackIntegers.pop();
// if we try to remove the element again, it will throw an exception
// that we can now catch
stackIntegers.pop();
} catch (exception const& excep) {
cerr << "Exception: " << excep.what() << endl;
return -1;
}
return 0;
}

After we look at the output, we’ll see why we need to know how to create general template classes and generic methods. Here’s the output:

501
The stack is not empty.
500
The stack is not empty.
500

Exception: Stack<>::pop(): empty stack
  • Lines 9–46 The code above implements a generic stack class (Stack<T>) using a vector to store elements. The stack supports the following operations: push(), pop(), top(), and empty().

  • Line 50: In the main() function, a stackIntegers named instance of the Stack<int> class is created.

  • Lines 53 and 54: Integer elements (500 and 501 ...