Singly linked list implementation I feel like there is room for improvement in the push/pop methods. Any suggestions?

#include &lt;exception&gt;

template &lt;typename T&gt;
class List
{
public:

                    List();
                    ~List();
    void            PushBack(const T &amp;data);
    void            PushFront(const T &amp;data);
    void            PopBack();
    void            PopFront();
    void            Clear();    
    bool            IsEmpty() const;
    unsigned int    Size() const;
    T&amp;              Front() const;
    T&amp;              Back() const;

private:

    template &lt;typename T&gt;
    struct Node
    {
        Node(const T &amp;data) : data(data), next(NULL) {}
        T      data;
        Node  *next;
    };

    Node&lt;T&gt; *head;
    Node&lt;T&gt; *tail;
};

template &lt;typename T&gt;
List&lt;T&gt;::List()
    : head(NULL),
      tail(NULL)
{

}

template &lt;typename T&gt;
List&lt;T&gt;::~List()
{
    Clear();
}

template &lt;typename T&gt;
void List&lt;T&gt;::PushBack(const T &amp;data)
{   
    if ( !head )
    {
        head = new Node&lt;T&gt;(data);
        tail = head;
        return;
    }

    tail-&gt;next = new Node&lt;T&gt;(data);
    tail = tail-&gt;next;
}

template &lt;typename T&gt;
void List&lt;T&gt;::PushFront(const T &amp;data)
{
    Node&lt;T&gt; *tmp = head;
    head = new Node&lt;T&gt;(data);
    head-&gt;next = tmp;

    if ( !tail )
    {
        tail = head;
    }
}

template &lt;typename T&gt;
void List&lt;T&gt;::PopBack()
{
    //empty list
    if ( !head )
    {
        throw std::out_of_range("Can't pop from empty list");
    }

    //list with one element
    if ( head == tail )
    {
        delete head;
        head = NULL;
        tail = NULL;
        return;
    }

    Node&lt;T&gt; *current = head;
    while ( current-&gt;next != tail )
    {
        current = current-&gt;next;
    }

    delete tail;
    tail = current;
    tail-&gt;next = NULL;
}

template &lt;typename T&gt;
void List&lt;T&gt;::PopFront()
{
    //empty list
    if ( !head )
    {
        throw std::out_of_range("Can't pop from empty list");
    }

    //list with one element
    if ( head == tail )
    {
        delete head;
        head = NULL;
        tail = NULL;
        return;
    }

    Node&lt;T&gt; *tmp = head-&gt;next;
    delete head;
    head = tmp;
}

template &lt;typename T&gt;
void List&lt;T&gt;::Clear()
{
    Node&lt;T&gt; *current = head;
    while ( head )
    {
        current = head;
        head = head-&gt;next;
        delete current;
    }

    head = NULL;
    tail = NULL;
}

template &lt;typename T&gt;
bool List&lt;T&gt;::IsEmpty() const
{
    return ( head == NULL );
}

template &lt;typename T&gt;
unsigned int List&lt;T&gt;::Size() const
{
    unsigned int size = 0;
    for ( Node&lt;T&gt; *current = head; current; current = current-&gt;next )
    {
        ++size;
    }

    return size;
}

template &lt;typename T&gt;
T&amp; List&lt;T&gt;::Front() const
{
    if ( !head )
    {
        throw std::out_of_range("Can't return value from empty list");
    }

    return head-&gt;data;
}

template &lt;typename T&gt;
T&amp; List&lt;T&gt;::Back() const
{
    if ( !head )
    {
        throw std::out_of_range("Can't return value from empty list");
    }

    return tail-&gt;data;
}
Consider using a different naming convention for your data members and methods, such as camelCase or snake_case.  Your user-defined types are already uppercase, which is okay.  Whichever you choose, it's more readable to keep them separate.
The push/pop methods here imply that this is a stack implementation, but a linked list should be capable of inserting or removing a node at any location in the list.  Consider adding additional functions for this.  For an idea of typical linked list functions, read this.
Since you're using a list class, you should have a size member to maintain.  Your Size() method is calculating the size at each call by traversing, which is O(n).

Instead, have a size data member and update it with other operations:


initialize to 0 in the initializer list
increment with each push
decrement with each pop
reset to 0 with each clear


When you call Size(), it should just return the data member value, which is O(1).

It should also return a std::size_t.  It is closest to the return type used in STL containers, and a very large list size may not fit inside an unsigned int.
Instead of having a return in PushFront(), put the last two lines into an else block.
Shouldn't popBack() check tail if PopFront() checks head?  Although they may be pointing to the same node if there's only one node, but the intent is more clear this way.
You should probably also have a Front() and Back() that return a T const&amp;, in case the reference will not be modified or a const value is needed.
You should have some way of displaying the list.  For that, consider overloading operator&lt;&lt; for the List class (instead of a display function), allowing you to do this:

List list;
std::cout &lt;&lt; list;


You could also overload Node's operator, allowing you to output a node within the List class.
std::out_of_range is defined in &lt;stdexcept&gt;, not &lt;exception&gt;.