Superior improved stack implementation using a linked list This is a followup to


Improved stack implementation using a linked list
Simple stack implementation using linked list


Please review my hopefully improved stack implementation


As suggested by some answers to my previous code, some of the functions can be overloaded to provide versions of return by value, return by reference and const or pass by value, pass by reference and const, but the function definitions are almost the same so I did not add it here.
Regarding pointers, I know std::unique_ptr will be better and I already saw an implementation through an answer to my previous code, but I like to play with normal pointers right now.


template&lt;class T&gt;
class Stack {
    using stacksize = std::size_t;
public:
    Stack() : first{nullptr}, n{0} {}
    stacksize size() const { return n; }
    bool empty() const { return n == 0; }
    Stack(const Stack&amp;);
    Stack(Stack&amp;&amp;);
    Stack&amp; operator=(Stack);
    Stack&amp; operator=(Stack&amp;&amp;);
    T&amp; operator[](const stacksize&amp; i) {
        Node* traverse = first;
        stacksize x = 0;
        while (x &lt; i) {
            traverse = traverse-&gt;next;
            ++x;
        }
        return traverse-&gt;item;
    }
    void push(const T&amp;);
    void pop();
    T&amp; peek() const;
    ~Stack() {
        while (!empty()) {
            pop();
        }
    }
private:
    struct Node {
        T item;
        Node* next;
        Node(const T&amp; t, Node* link) :item{t}, next{link} { }
    };
    Node* first;
    stacksize n;
};

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

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

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

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

template&lt;class T&gt;
void Stack&lt;T&gt;::push(const T&amp; t) {
    first = new Node{t,first};
    ++n;
}

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

template&lt;class T&gt;
T&amp; Stack&lt;T&gt;::peek() const {
    return first-&gt;item;
}
Code Review
I find your placement of &amp; inconsistent with *
    Node(const T &amp; t, Node* link) :item{t}, next{link} { }

And r-value reference declaration stranger still
    Stack(Stack &amp; &amp; );  // I am surprised that compiled. As each `&amp;` is a separate token
                        // While `&amp;&amp;` is a single token.

This is all part of the type information. Put it with the type.
    Node(const T&amp; t, Node* link) :item{t}, next{link} { }
    Stack(Stack&amp;&amp; rhs);

You provide a push by copy.
void push(const T &amp; );

and you are familiar with move semantics. Why not provide a push by move?
void push(T&amp;&amp; val);

Very Minor personal preference.
Personally I prefer const on the right of the type. The rule is that const binds left unless it is on the very left hand side then it binds right. There is one obsecure corner case were this makes a difference. But it is obscure so don't worry.
    Node(T const&amp; t, Node* link) :item{t}, next{link} { }

I just find it easier when reading types (as you read them right to left).
    char const * const  x;
    // x is &quot;const pointer&quot; to a &quot;const char&quot;

    char const *   x;
    // x is &quot;pointer&quot; to a &quot;const char&quot;

    char * const  x;
    // x is &quot;const pointer&quot; to a &quot;char&quot;