Let say I define some kind of container A
:
struct A
{
iterator begin(){ return iterator(this,0); }
const iterator cbegin() const { return iterator(this, last());}
//...
};
Suppose now I want to declare the iterator
(part of A):
struct A::iterator
{
iterator ( A* ptr, size_t idx){};
//...
};
Which I would use like:
const A a;
A::iterator it = a.cbegin();
That does not work because the pointer passed to the constructor of iterator
is non-const.
The ideal solution would be something like a specific constructor that return a const object:
const A::iterator( const StringUtfInterface *p, size_t s); //Not valid
This is (obviously) not valid in C++. I wonder what is the approach to this problem?
Do I really need to declare/define a new const_iterator class? const
keyword is not enough?
Related questions (but not the same):
- Why does C++ not have a const constructor?
- Get iterator for const reference
const
keyword is not enough?
Actually, const
keyword is too much: it forces you to write
const A::iterator it = a.cbegin();
which prevents you from using ++it
later on.
You need to provide two separate classes, but it does not mean that you have to write the code twice. You can structure an implementation of your iterator in such a way that a common class that does all the work is embedded in both constant and non-constant iterator implementations, which expose the relevant methods of the embedded implementation to the callers.
What about just overloading the constructor of iterator
to support constant container too?
struct A::iterator {
iterator(A* ptr, size_t idx) {}
iterator(const A* ptr, size_t idx) {}
//...
};
In this way it is not necessary to define two separate classes and you will always obtain (implicitly) the right iterator depending on your container constness.
UPDATE
Following comment, you may use a template such as (not full implementation)
struct A {
template<class T>
struct base_iterator {
private:
T* _ptr;
public:
base_iterator(T* ptr, size_t idx) : _ptr(ptr) {}
T operator*() { return *_ptr; }
//...
};
typedef base_iterator<A> iterator;
typedef base_iterator<const A> const_iterator;
iterator begin() { return iterator(this, 0); }
const_iterator cbegin() const { return const_iterator(this, 0); }
//...
};