#pragma once
#include <utility>

template<typename T> struct 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 ** cr = &head;
		for ( node * nx = o.head; nx; nx = nx->next ) {
			*cr = new node{ nx->value }; /***/
			cr = &(*cr)->next;
		}
		*cr = nullptr;
	}

	void clear() {
		for ( node * nx = head; nx; ) {
			node * cr = nx;
			nx = cr->next;
			delete cr;
		}
		head = nullptr;
	}

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

	stack & operator=( const stack<T> & o ) {
		if ( this == &o ) return *this;
		clear();
		copy( o );
		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 v = std::move( n->value );
		delete n;
		return v;
	}
};
