C++11 Singly Linked List with raw pointers Regarding C++, I have an experience in writing only short non-object-oriented programs and competitive programming challenges.

I would like to get your feedback about my C++ style, design decisions, and overall quality.

The below is the implementation of a Singly Linked List containing a multiset of values of type T. Type T is required to provide equal to operator. The class supports the following operations:


push a new value to the front of the list   
push a new value to the end of the list   
remove the first encountered occurrence of a given value
check if the list contains a given value
get the number of elements in the list
print the list in a pretty format
swap two lists


For the design, I decided to use both head and tail pointers to make both inserts constant time operations. For now, all pointers are raw pointers. The Node class is the internal class of LinkedList and an instance of LinkedList is responsible to delete its nodes. I decided to do that because this allows freeing the memory iteratively instead of recursively, which could cause problems if stack size is limited.

/* Singly Linked List by @pkacprzak */

#ifndef LINKED_LIST_HH__
#define LINKED_LIST_HH__

#include &lt;ostream&gt;

template&lt;typename T&gt;
class LinkedList {
public:
    LinkedList() {}

    LinkedList(const LinkedList&amp; x) {
        auto cur = x.head;
        while (cur != nullptr) {
            pushBack(cur-&gt;val);
            cur = cur-&gt;next;
        }
    }

    LinkedList&amp; operator=(const LinkedList&amp; rhs) {
        LinkedList tmp(rhs);
        swap(*this, tmp);
        return *this;
    }

    ~LinkedList() {
        auto cur = head;
        while (cur != nullptr) {
            auto tmp = cur;
            cur = cur-&gt;next;
            delete tmp;
            tmp = nullptr;
        }
    }

    void pushFront(T val) {
        auto node = new Node(val);
        node-&gt;next = head;
        if (head == nullptr) {
            tail = node;
        }
        head = node;
        ++sz;
    }

    void pushBack(T val) {
        auto node = new Node(val);
        if (head == nullptr) {
            head = node;
        } else {
            tail-&gt;next = node;
        }
        tail = node;
        ++sz;
    }

    bool contains(T val) const {
        auto cur = head;
        while (cur != nullptr) {
            if (cur-&gt;val == val) {
                return true;
            }
            cur = cur-&gt;next;
        }
        return false;
    }

    void removeValue(T val) {
        if (head == nullptr) return;
        if (head-&gt;val == val) {
            auto cur = head;
            head = head-&gt;next;
            delete cur;
            if (head == nullptr) {
                tail = nullptr;
            }
            --sz;
        } else {
            auto cur = head-&gt;next;
            auto prev = head;
            while (cur != nullptr) {
                if (cur-&gt;val == val) {
                    prev-&gt;next = cur-&gt;next;
                    if (cur == tail) {
                        tail = prev;
                    }
                    delete cur;
                    --sz;
                    return;
                }
                prev = cur;
                cur = cur-&gt;next;
            }
        }
    }

    int size() const {
        return sz;
    }

    friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const LinkedList&amp; x) {
        auto cur = x.head;
        os &lt;&lt; "[";
        while (cur != nullptr) {
            os &lt;&lt; cur-&gt;val;
            if (cur != x.tail) {
                os &lt;&lt; ",";
            }
            cur = cur-&gt;next;
        }
        os &lt;&lt; "]";
        return os;
    }

    friend void swap(LinkedList&amp; a, LinkedList&amp; b) {
        std::swap(a.head, b.head);
        std::swap(a.tail, b.tail);
    }

private:
    struct Node {
        Node(T val_) : val(val_) {}
        T val;
        Node* next = nullptr;
    };
    Node* head = nullptr;
    Node* tail = nullptr;
    int sz = 0;
};
#endif
Item 1. swap does not handle sz member

Item 2.
No move constructor or operator= (no move semantic at all)

Item 3. Functions like contains get parameters by value - which is Ok for primitive types T and could be expensive for complex types

Item 4. No iterators - so not usable with algorithms. And also implementing something like remove_all is almost impossible - no indication of the remove success (except comparing size before and after), no possibility to continue scanning from the last location...

I suggest to take the std::forward_list http://en.cppreference.com/w/cpp/container/forward_list and try to emulate its API a lot closer then current attemp. Or justify your design choices explaining in more details why you think your change in the standard list API is superior to the stl approach.

Generally I like how the code looks and compiles. :)