Does `const_iterator` really need to be a differen

2019-07-18 17:22发布

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):

2条回答
乱世女痞
2楼-- · 2019-07-18 18:01

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); }
  //...
};
查看更多
Emotional °昔
3楼-- · 2019-07-18 18:15

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.

查看更多
登录 后发表回答