Recursive version. The only interesting function:
List& 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 <iostream>
#include <memory>
struct List
{
struct Node
{
int val;
std::unique_ptr<Node> next;
Node(){}
Node(int v, Node* oldTail)
: val(v)
, next(nullptr)
{
oldTail->next.reset(this);
}
friend std::ostream& operator<<(std::ostream& s, Node const& data)
{
return s << data.val << " ";
}
};
Node sentinal;
Node* tail;
public:
List()
: tail(&sentinal)
{}
bool empty() const
{
return &sentinal == tail;
}
int& head()
{
// Pre-Condition not empty
return sentinal.next->val;
}
List& append(int val)
{
tail = new Node(val, tail);
return *this;
}
List& pop()
{
// Pre-Condition not empty
sentinal.next.reset(sentinal.next->next.release());
tail = sentinal.next.get() ? tail : &sentinal;
return *this;
}
List& reverse();
friend std::ostream& operator<<(std::ostream& s, List const& data)
{
for(Node* loop = data.sentinal.next.get(); loop != nullptr; loop=loop->next.get())
{ s << *loop;
}
return s << "\n";
}
};