The original question can be seen here: Stack implementation in C++ using linked list
Changes (with the help of Martin):
- Added copy constructor and assignment operator overload
- Changed return type of peek() to const T& rather than T (this prevents unnecessary copying of data)
- Changed return type of pop() to void; it now only removes the top item rather than returning it on top. The user can call peek() and then call pop() to retrieve and then delete the item. This means we don't have to return T by value, and also maintains the "Strong Exception Guarantee".
- Fixed a bug in pop() where the new head is deleted rather than the old one
#ifndef TEST_STACK_H
#define TEST_STACK_H
#include <stdexcept>
template <class T>
class stack {
struct node {
T data;
node* previous;
node(T data, node *previous) : data(data), previous(previous) {}
};
node* head = nullptr;
int size = 0;
int max = -1; // -1 so isFull() == false when default constructor used
public:
stack() = default;
stack(int max) {
if (max <= 0) throw std::out_of_range("stack size must be > 0");
this->max = max;
}
// copy constructor
stack(stack const& rhs) :
head(copyList(rhs.head)),
size(rhs.size),
max(rhs.size) {}
// assignment operator
stack& operator = (stack const& rhs)
{
stack tmp(rhs);
swap(tmp);
return *this;
}
~stack() {
node* n = head;
while (n != nullptr) {
node* previous = n->previous;
delete n;
n = previous;
}
}
void push(const T &object) {
if (isFull()) throw std::overflow_error("cannot push to a full stack");
head = new node(object, head);
++size;
}
const void pop() {
if (head == nullptr) throw std::underflow_error("cannot get item from empty stack");
node* old = head;
head = head->previous;
--size;
delete old;
}
T peek() {
if (head == nullptr) throw std::underflow_error("cannot get item from empty stack");
return head->data;
}
int getSize() {
return size;
}
bool isFull() {
return size == max;
}
bool isEmpty() {
return head == nullptr;
}
void swap(stack& other) noexcept
{
using std::swap;
swap(head, other.head);
swap(size, other.size);
swap(max, other.max);
}
private:
node* copyList(node* l)
{
if (l == nullptr) {
return nullptr;
}
return new node{l->data, copyList(l->previous)};
}
};
#endif