// CMSC 341 - Spring 2020 - Project 0 // stack.h: a templated, linked list-based stack implementation // Assignment: // (1) Complete the copy constructor // (2) Complete the assignment operator // (3) Complete the destructor // (4) Write a test program (mytest.cpp) to test copy and assignment // (5) Verify destructor by running the test program in Valgrind #ifndef _STACK_H #define _STACK_H #include #include using std::ostream; using std::cout; using std::endl; using std::range_error; // Forward declarations template class Stack; template class Node; template ostream& operator<<(ostream&, const Node&); // Node class for linked list template class Node { friend Stack; public: Node(T data = T(), Node *next = nullptr) { _data = data; _next = next; } friend ostream& operator<< (ostream &sout, const Node &x); private: T _data; Node *_next; }; // Overloaded insertion operator. Must be overloaded for the template // class T, or this won't work! template ostream& operator<<(ostream &sout, const Node &x) { sout << "Data: " << x._data; return sout; } // Stack class. Linked-list implementation of a stack. Uses the Node // class. template class Stack { public: // Constructor Stack(); // Copy constructor, assignment operator, and destructor // DO NOT IMPLEMENT HERE. SEE BELOW. Stack(const Stack &rhs); const Stack& operator=(const Stack& rhs); ~Stack(); // Stack operations: push(), top(), and pop() void push(const T& data); const T& top() const; void pop(); // Helpful functions bool empty() const; // Returns 'true' if stack is empty void dump() const; // Dump contents of the linked list private: Node *_head; // *************************************************** // Any private helper functions must be delared here! // *************************************************** }; template Stack::Stack() { _head = nullptr; } template Stack::Stack(const Stack& rhs) { // ******************************** // Implement the copy constructor // ******************************** } template const Stack& Stack::operator=(const Stack& rhs) { // ********************************** // Implement the assignment operator // ********************************** } template Stack::~Stack() { // ************************* // Implement the destructor // ************************* } template void Stack::push(const T& data) { Node *tmpPtr = new Node(data); tmpPtr->_next = _head; _head = tmpPtr; } template const T& Stack::top() const { if ( empty() ) { throw range_error("Stack::top(): attempt to read empty stack."); } return _head->_data; } template void Stack::pop() { if ( empty() ) { throw range_error("Stack::pop(): attempt to pop from an empty stack."); } Node *tmpPtr = _head->_next; delete _head; _head = tmpPtr; } template bool Stack::empty() const { return _head == nullptr; } template void Stack::dump() const { Node *nodePtr = _head; while ( nodePtr != nullptr ) { cout << nodePtr->_data << endl; nodePtr = nodePtr->_next; } } #endif