I made a post that follows from this here. I made most of changes that I could understand from the following link, and here is now an update to that original post. I just want to see if there is any major changes that I need to consider making and perhaps to gain some more insight into how to achieve making those changes.
Here is the header file:
#ifndef Stack_h
#define Stack_h
template <class T>
class Stack {
private:
struct Node {
T data;
Node* next;
};
Node* _top;
// Used for destructor to delete elements
void do_unchecked_pop();
// Use for debugging purposes and for overloading the << operator
void show(std::ostream &str) const;
public:
// Rule of 5
Stack() : _top(nullptr){} // empty constructor
Stack<T>(Stack<T> const& value); // copy constructor
Stack<T>(Stack<T>&& move) noexcept; // move constuctor
Stack<T>& operator=(Stack&& move) noexcept; // move assignment operator
~Stack(); // destructor
// Overload operators
Stack& operator=(Stack const& rhs);
friend std::ostream& operator<<(std::ostream& str, Stack<T> const& data) {
data.show(str);
return str;
}
// Member functions
void swap(Stack& other) noexcept;
bool empty() const;
int size() const;
void push(const T& theData);
void push(T&& theData);
T& top() const;
void pop();
};
template <class T>
Stack<T>::Stack(Stack<T> const& value) : _top(nullptr) {
for(Node* loop = value._top; loop != nullptr; loop = loop->next) {
push(loop->data);
}
}
template <class T>
Stack<T>::Stack(Stack<T>&& move) noexcept : _top(nullptr) {
move.swap(*this);
}
template <class T>
Stack<T>& Stack<T>::operator=(Stack<T> &&move) noexcept {
move.swap(*this);
return *this;
}
template <class T>
Stack<T>::~Stack() {
while(_top != nullptr) {
do_unchecked_pop();
}
}
template <class T>
Stack<T>& Stack<T>::operator=(Stack const& rhs) {
Stack copy(rhs);
swap(copy);
return *this;
}
template <class T>
void Stack<T>::swap(Stack<T> &other) noexcept {
using std::swap;
swap(_top,other.top);
}
template <class T>
bool Stack<T>::empty() const {
return _top == nullptr;
}
template <class T>
int Stack<T>::size() const {
int size = 0;
Node* current = _top;
while(current != nullptr) {
size++;
current = current->next;
}
return size;
}
template <class T>
void Stack<T>::push(const T &theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->next = nullptr;
if(_top != nullptr) {
newNode->next = _top;
}
_top = newNode;
}
template <class T>
void Stack<T>::push(T&& theData) {
Node* newNode = new Node;
newNode->data = std::move(theData);
newNode->next = nullptr;
if(_top != nullptr) {
newNode->next = _top;
}
_top = newNode;
}
template <class T>
T& Stack<T>::top() const {
return _top->data;
}
template <class T>
void Stack<T>::do_unchecked_pop() {
Node* tmp = _top->next;
delete _top;
_top = tmp;
}
template <class T>
void Stack<T>::pop() {
if(_top == nullptr) {
throw std::invalid_argument("the Stack is empty!");
}
do_unchecked_pop();
}
template <class T>
void Stack<T>::show(std::ostream &str) const {
for(Node* loop = _top; loop != nullptr; loop = loop->next) {
str << loop->data << "\t";
}
str << "\n";
}
#endif /* Stack_h */
Here is the main.cpp file that tests the latter:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <ostream>
#include "Stack.h"
int main(int argc, const char * argv[]) {
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Stack Using Linked List //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
Stack<int> obj;
obj.push(2);
obj.push(4);
obj.push(6);
obj.push(8);
obj.push(10);
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Displaying Stack Contents---------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Pop Stack Element -------------------";
std::cout<<"\n--------------------------------------------------\n";
obj.pop();
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Get the size of stack -------------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj.size() << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Re-Add Poped Element---------------";
std::cout<<"\n--------------------------------------------------\n";
obj.push(10);
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Print top element --------------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj.top() << std::endl;
return 0;
}
Node
constructor? \$\endgroup\$ – vnp Jun 27 '18 at 23:21