I am implementing a simple iterator for some custom container (based on a list):
template <class T, class Link>
class single_iterator
{
public:
using iterator_category = std::forward_iterator_tag;
//A value is not T but T*, because the list is a contaner of elements of type T *.
using value_type = T *;
//Required by std::iterator_traits in GCC.
using difference_type = std::ptrdiff_t;
using pointer = value_type *;
using reference = value_type &;
single_iterator(Link *p) : pCur(p) {}
T * operator-> () const { return cur(); }
T * operator* () const { return cur(); }
single_iterator & operator++ ()
{
this->MoveNext();
return *this;
}
single_iterator operator++ (int)
{
single_iterator tmp = *this;
this->MoveNext();
return tmp;
}
bool operator == (const single_iterator & r) const
{
return this->link() == r.link();
}
bool operator != (const single_iterator & r) const
{
return !(*this == r);
}
private:
//! Results in undefined behavior if the iterator is end().
T * cur() const { return static_cast<T *>(pCur); }
void MoveNext() { pCur = pCur->next(); }
Link * link() const { return pCur; }
Link * pCur;
};
then I declare iterator
and const_iterator
in my container and implement begin()
and end()
:
template <class T, class Link, class Derived>
class container
{
public:
using value_type = T *;
using iterator = single_iterator<T, Link>;
using const_iterator = single_iterator<const T, const Link>;
iterator begin() { return first(); }
const_iterator begin() const { return first(); }
};
and when I use the iterator like this it does not compile:
#include <iostream>
#include <vector>
struct A
{
void func()
{
container<A>::const_iterator i = m_v.begin();
}
container<A> m_v;
};
int main()
{
A a;
a.func();
return 0;
}
because const_interator
can't be constructed from iterator
.
What is the right way to implement this conversion with a minimal code duplication and defining separate classes for const_iterator
and iterator
?
See the same code with std::vector.
EDIT1: The code like this compiles:
struct A
{
operator A() { return *this;}
};
int main()
{
A a;
return 0;
}
so it is possible to define type conversion operator by adding const
and const_iterator
will convert to itself. But it looks a bit strange...