#pragma once
#include <utility>

template<typename T> class stack {
	struct node {
		T value;
		node* next;

		node( const T& v, node* n = nullptr ) : value(v), next(n) {}
	};
	node* head;

	void copy(const stack<T>& o) {
		node** crnt = &head;
		for ( node* next = o.head; next; next = next->next ) {
			*crnt = new node{ next->value }; /***/
			crnt = &(*crnt)->next;
		}
		*crnt = nullptr;
	}
public:
	void clear() {
	    for ( node* next = head; next; ) {
			node* crnt = next;
			next = crnt->next;
			delete crnt;
		}
		head = nullptr;
	}

	stack() : head(nullptr) {}
	stack(const stack<T>& o) { copy(o); }
	stack(stack<T>&& o) : head(o.head) { o.head = nullptr; }
	~stack() { clear(); }

	stack& operator= (const stack<T>& o) {
		if ( this == &o ) return *this;
		clear();
		copy(o);
		return *this;
	}

	stack& operator= (stack<T>&& o) {
		if ( this == &o ) return *this;
		head = o.head;
		o.head = nullptr;
		return *this;
	}

	bool empty() const { return head == nullptr; }

	void push(const T& value) { head = new node{ value, head };  /***/ }

	T pop() {
		node* n = head;
		head = n->next;
		T x = std::move(n->value);
		delete n;
		return x;
	}
};
