/*
* Another variation on the linked stack, this time using the shared_ptr
* library class to manage memory allocation. We no longer need a
* destructor.
*/
#ifndef _lnkstack3_h_
#define _lnkstack3_h_
#include <utility>
#include <memory>
#include <iostream>
using std::shared_ptr;
template <typename T>
class Stack {
public:
Stack() {
m_size = 0;
std::cout << "== Creating Stack ==" << std::endl;
}
// Clean up any remaining nodes.
~Stack() {
// This destructor exists only to print.
std::cout << "== Destroying Stack (" << m_size << " nodes) =="
<< std::endl;
}
// Push the argument item.
void push(const T &itm) {
// Create a new node, holding it in a unique ptr. (The
// make_unique method is from the 2014 standandard.)
m_head = std::make_shared<node>(itm, m_head);
++m_size;
}
// Pop the argument item, and return true, or return false if the
// the stack is empty.
bool pop(T &itm) {
if(!m_head) return false;
itm = m_head->data();
m_head = m_head->next();
--m_size;
return true;
}
// Convenience to pop and return the top object. Only works
// for types where T() is a valid expression.
T pop() {
T ret;
if(pop(ret)) return ret;
return T();
}
// Tell if empty.
bool empty() {
return m_head == nullptr;
}
// Report the size
int size() {
return m_size;
}
private:
// Nodes for the linked list.
class node {
public:
// Constructor for a node. Saves the arguments.
node(const T &d, shared_ptr<node> n = nullptr) {
m_data = d;
m_next = n;
std::cout << "== Creating node [" << d << "] =="
<< std::endl;
}
~node() {
// This destructor exists only to print.
std::cout << "== Destroying node [" << m_data << "] =="
<< std::endl;
}
const T& data() { return m_data; }
shared_ptr<node> next() { return m_next; }
private:
T m_data;
shared_ptr<node> m_next;
};
shared_ptr<node> m_head;
int m_size;
};
#endif