Custom iterator for a linked list class I have made a LinkedList class. This is a singly-linked-list and I want to make a forward_iterator for this class without using Boost. I have made the code and I want to know whether I have implemented it correctly. The source I referred to make this code is here.

template &lt;class T&gt;
struct node
{
    T data;
    node *next;
};

template &lt;class T&gt;
class LinkedList
{
    private :
    node&lt;T&gt; *start;
    unsigned int numElements;
    // Assume all functions are implemented
};


Iterator Code :

class iterator : public std::iterator&lt;std::forward_iterator_tag,node&lt;T&gt;*&gt;
{
    node&lt;T&gt;* itr;

    public :

    iterator (node&lt;T&gt;* temp) : itr(temp) {}
    iterator (const iterator&amp; myitr) : itr(myitr.itr) {}
    iterator&amp; operator++ 
    {
        itr = itr-&gt;next;
        return *this;

    }
    bool operator== (const iterator&amp; rhs) 
    {
        return itr == rhs.itr;

    }
    bool operator!= (const iterator&amp; rhs) 
    {
        return itr != rhs.itr;

    }
    T&amp; operator*()
    {
        return itr-&gt;data;
    }

};


Is the above implementation correct? If not, then what changes should I make?  Also, does anything else need to be implemented?
Your iterator is missing a few important details:

You should provide the pre- and post-increment operators (++it and it++). Currently, you only have the pre-increment version.

It might also be good to provide the -&gt; operator, since some people prefer the it-&gt;something syntax over the (*it).something one.

The comparison and dereference operators should be const. Remember Const Correctness.

The copy constructor is just performing a memberwise copy of the underlying data, so you don't need to provide one and can let the compiler default it.

The Standard Library containers always provide two flavors of iterators, the iterator type, pointing to mutable data, and the const_iterator type, pointing to immutable data. It is easy to adapt your class to support both by providing a conversion operator and inheriting from std::iterator (see the following example).

Decide which course of action should be taken when incrementing and dereferencing an invalid iterator. E.g.: list.end()++;. Should it trigger an assertion? Throw an exception? Do nothing as it is now? I would at least assert to help the debugging process. You might find exceptions more appropriate in your context.


The above points applied to your code:
#include &lt;cassert&gt;      // assert
#include &lt;cstddef&gt;      // ptrdiff_t
#include &lt;iterator&gt;     // iterator
#include &lt;type_traits&gt;  // remove_cv
#include &lt;utility&gt;      // swap

template
&lt;
    class Type,
    class UnqualifiedType = std::remove_cv_t&lt;Type&gt;
&gt;
class ForwardIterator 
    : public std::iterator&lt;std::forward_iterator_tag,
                           UnqualifiedType,
                           std::ptrdiff_t,
                           Type*,
                           Type&amp;&gt;
{
    node&lt;UnqualifiedType&gt;* itr;

    explicit ForwardIterator(node&lt;UnqualifiedType&gt;* nd) 
        : itr(nd) 
    { 
    }

public:

    ForwardIterator()   // Default construct gives end.
        : itr(nullptr) 
    { 
    }

    void swap(ForwardIterator&amp; other) noexcept
    {
        using std::swap;
        swap(itr, other.iter);
    }

    ForwardIterator&amp; operator++ () // Pre-increment
    {
        assert(itr != nullptr &amp;&amp; &quot;Out-of-bounds iterator increment!&quot;);
        itr = itr-&gt;next;
        return *this;
    }

    ForwardIterator operator++ (int) // Post-increment
    {
        assert(itr != nullptr &amp;&amp; &quot;Out-of-bounds iterator increment!&quot;);
        ForwardIterator tmp(*this);
        itr = itr-&gt;next;
        return tmp; 
    }

    // two-way comparison: v.begin() == v.cbegin() and vice versa
    template&lt;class OtherType&gt;
    bool operator == (const ForwardIterator&lt;OtherType&gt;&amp; rhs) const
    {
        return itr == rhs.itr;
    }
    
    template&lt;class OtherType&gt;
    bool operator != (const ForwardIterator&lt;OtherType&gt;&amp; rhs) const
    {
        return itr != rhs.itr;
    }

    Type&amp; operator* () const
    {
        assert(itr != nullptr &amp;&amp; &quot;Invalid iterator dereference!&quot;);
        return itr-&gt;data;
    }

    Type&amp; operator-&gt; () const
    {
        assert(itr != nullptr &amp;&amp; &quot;Invalid iterator dereference!&quot;);
        return itr-&gt;data;
    }

    // One way conversion: iterator -&gt; const_iterator
    operator ForwardIterator&lt;const Type&gt;() const
    {
        return ForwardIterator&lt;const Type&gt;(itr);
    }
};

// `iterator` and `const_iterator` used by your class:
typedef ForwardIterator&lt;T&gt; iterator;
typedef ForwardIterator&lt;const T&gt; const_iterator;

Note: In the example, I've assumed that the end of your list or an invalid iterator are marked by a null pointer. You'll need to change that if you are using some other method, such as a dummy sentry node.