#ifndef STACK_HPP_INCLUDED #define STACK_HPP_INCLUDED #include // std::forward #include // std::move #include // std::runtime_error class empty_stack : public std::runtime_error { public: empty_stack(std::string const& what_arg) : std::runtime_error{what_arg} {}; }; template class Stack { public: Stack() : head{nullptr} {}; ~Stack(); template void add(U&&); T remove(); inline bool empty() const { return head == nullptr; }; private: struct Node { T data; Node* next; template Node(U&& d, Node* n) : data{std::forward(d)}, next{n} {}; }; Node* head; }; template Stack::~Stack() { // Rewriting functionality of remove here avoids a call to the move // constructor for each element in the stack. For code golf, use: // while(!empty()) remove(); while(!empty()) { auto old_head = head; head = head->next; delete old_head; } } template template void Stack::add(U&& t) { head = new Node{std::forward(t), head}; } template T Stack::remove() { if(empty()) throw empty_stack{"Remove called on empty stack."}; auto old_head = head; auto old_data = std::move(head->data); head = head->next; delete old_head; return old_data; } #endif // STACK_HPP_INCLUDED