Linked List reversal Recursive version. The only interesting function:

        List&amp; List::reverse()
        {
            if (empty())
            {   return *this;
            }
            int val = head();
            //
            // The fun bit.
            // See if you can figure this bit out.
            return pop().reverse().append(val);
        }


The rest:

#include &lt;iostream&gt;
#include &lt;memory&gt;
struct List
{
    struct Node
    {
        int     val;
        std::unique_ptr&lt;Node&gt;   next;
        Node(){}
        Node(int v, Node* oldTail)
            : val(v)
            , next(nullptr)
        {
            oldTail-&gt;next.reset(this);
        }
        friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, Node const&amp; data)
        {
            return s &lt;&lt; data.val &lt;&lt; " ";
        }
    };
    Node    sentinal;
    Node*   tail;
    public:
        List()
            : tail(&amp;sentinal)
        {}
        bool empty() const
        {
            return &amp;sentinal == tail;
        }
        int&amp; head()
        {
            // Pre-Condition not empty
            return sentinal.next-&gt;val;
        }
        List&amp; append(int val)
        {
            tail = new Node(val, tail);
            return *this;
        }
        List&amp; pop()
        {
            // Pre-Condition not empty
            sentinal.next.reset(sentinal.next-&gt;next.release());
            tail = sentinal.next.get() ? tail : &amp;sentinal;
            return *this;
        }
        List&amp; reverse();
        friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, List const&amp; data)
        {
            for(Node* loop = data.sentinal.next.get(); loop != nullptr; loop=loop-&gt;next.get())
            {   s &lt;&lt; *loop;
            }
            return s &lt;&lt; "\n";
        }

};
See if you can figure this bit out.


Is this meant to be a Programming Puzzle?

You don't call append until after you finish calling reverse; reverse is recursive; so all the append calls will be called after all the reverse calls: and that explains why reverse will eventually terminate i.e. why the list will eventually be empty.

From a code-review point of view:


I fear that a recursive implementation might exceed your finite maximum stack size if the list is long.
You're deleting and creating new Node objects; you might instead be able to do it in a way that reuses existing Node instances.


Also, it should be spelled "sentinel".