Improved stack implementation using a linked list
Don't repeat code:

template&lt;class T&gt;
Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(const Stack&amp; s) {
    for (auto t = s.first; t != nullptr; t = t-&gt;next) {
        push(t-&gt;item);
    }
    return *this;
}


This is not really an assignment but an append. I think most people would not expect that. You should probably release the original list before copying over the source into this object.

An easier way to implement the assignment operator is to use the copy and swap idiom.

// Notice the pass by value creates an implicit copy.
// You then just swap the content of the current object
// with the parameter s.
// When the parameter goes out of scope it deletes the old
// data stack.
Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(Stack s) {
    std::swap(first,   s.first);
    std::swap(n,       s.n);
    return *this;
}


You move assignment leaks:

template&lt;class T&gt;
Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(Stack&amp;&amp; s) {
    first = s.first;
    n = s.n;
    s.first = nullptr;
    s.n = 0;
    return *this;
}


The current value of first is leaked. The best way to do this is to swap the content of this object with the incomming object.

template&lt;class T&gt;
Stack&lt;T&gt;&amp; Stack&lt;T&gt;::operator=(Stack&amp;&amp; s) {
    std::swap(first,   s.first);
    std::swap(n,       s.n);
    return *this;
}


Let the other object do the clean up when it goes out of scope.

You implemented a push by copy:

void push(const T&amp;);


Why not have a push by move:

void push(T&amp;&amp;);


I would make the Node structure a private implementation detail of stack. That way other people can not rely on that detail when they use your code.

template&lt;class T&gt;
class Stack {
     struct Node {....} 
};


Your peak creates a copy of the object.

   T Stack&lt;T&gt;::peek() const {
// ^ Return by value creates a copy.


I would return by reference. I would also rovide two version. One to return by const reference (for const version of the stack), and a normal return by reference so you can look at the top value and potentially alter it without removing it from the stack:

T const&amp; Stack&lt;T&gt;::peek() const { ....
T&amp;       Stack&lt;T&gt;::peek()       { ....


Your destructor checks empty() then calls pop() which checks empty(). This is a bit redundant. You could have a private version of pop that does not check empty.

~Stack() {
    while (!empty()) {
        noneCheckedPop();
    }

void Stack&lt;T&gt;::pop() {
    if (empty()) {
        throw std::out_of_range("underflow");
    }
    noneCheckedPop();
}

private:
void Stack&lt;T&gt;::noneCheckedPop() {
    Node&lt;T&gt;* oldfirst = first;
    first = first-&gt;next;
    delete oldfirst;
    --n;
}