www.digitalmars.com         C & C++   DMDScript  

c++ - STL standard containers accessors

reply "andrew" <user earth.com> writes:
Hi,
Sorry for not posting this in c++.stl but it does not seem to work for me.

I need to implement the Iterator design pattern. I wrote a ListCollection
class:

template <class Item>
class ListCollection : public Collection<Item>
{
 vector<Item> m_items;

public:

 // Collection implementation
 virtual void add(const Item& pItem) { m_items.push_back(pItem); }
 virtual void remove(const Item&) { }
 virtual size_t count() const { return m_items.size(); }
 virtual Item& get(size_t index) const { return m_items[index]; }
 virtual Iterator<Item>* create_iterator() { return new
ListIterator<Item>(this); }
};

The problem is with the const'ness of Item& get(size_t index) method.
Being constant, the method will call the const version of the std::vector
operator[]  which returns a const reference.
Hence, I receive a compilation error because it cannot convert the return
value from the const to non-const.

My Collection::get() method I found logic to be const but it seems it can't
be due to the implementation of the std::vector::operator[].

Looking to the std::vector class:

 const_reference operator[](size_type _Pos) const
  { // subscript nonmutable sequence
  return (*(begin() + _Pos));
  }

 reference operator[](size_type _Pos)
  { // subscript mutable sequence
  return (*(begin() + _Pos));
  }

Now, the question is why the 2nd version it's not const also ? Afterall, it
doesn't modify the vector. It's exactly as the first version.
I see that using the constant version of the std vector operator[] forces
the return value to be const also. But, as I see in my Collection class,
there are cases when you need to access the operator[] as const but without
returning the const element.
The const'ness of the operator[] should indicate that the operation does not
modify the container not necessary that the container itself is constant.

For my Collection class, I guess one way to still keep the const'ness of the
get() method  (and return a const Item&) is to have a set(const Item&,
size_t index) method. But i don't think it's nice.
My idea is that a Collection class is an encapsulation of as it's name says,
a collection of items. Modifying the elements should be allowed, i guess.

Maybe I am not getting it right. Please give some advices.

thanks.
Oct 10 2007
parent Arjan Knepper <arjan ask.me.to> writes:
andrew wrote:
 Hi,
 Sorry for not posting this in c++.stl but it does not seem to work for me.
 
 I need to implement the Iterator design pattern. I wrote a ListCollection
 class:
 
 template <class Item>
 class ListCollection : public Collection<Item>
 {
  vector<Item> m_items;
 
 public:
 
  // Collection implementation
  virtual void add(const Item& pItem) { m_items.push_back(pItem); }
  virtual void remove(const Item&) { }
  virtual size_t count() const { return m_items.size(); }
  virtual Item& get(size_t index) const { return m_items[index]; }
  virtual Iterator<Item>* create_iterator() { return new
 ListIterator<Item>(this); }
 };
 
 The problem is with the const'ness of Item& get(size_t index) method.
 Being constant, the method will call the const version of the std::vector
 operator[]  which returns a const reference.
 Hence, I receive a compilation error because it cannot convert the return
 value from the const to non-const.
 
 My Collection::get() method I found logic to be const but it seems it can't
 be due to the implementation of the std::vector::operator[].
 
 Looking to the std::vector class:
 
  const_reference operator[](size_type _Pos) const
   { // subscript nonmutable sequence
   return (*(begin() + _Pos));
   }
 
  reference operator[](size_type _Pos)
   { // subscript mutable sequence
   return (*(begin() + _Pos));
   }
 
 Now, the question is why the 2nd version it's not const also ? Afterall, it
 doesn't modify the vector. 
No but the user of the return'ed reference might modify the vector. It's exactly as the first version.
 I see that using the constant version of the std vector operator[] forces
 the return value to be const also. But, as I see in my Collection class,
 there are cases when you need to access the operator[] as const but without
 returning the const element.
In that particular case don't use the return by 'reference'. Since that reference has to be const as well otherwise the 'const contract' might be broken. Use return by value: virtual Item get(size_t index) const { Item result = m_items[index]; return ( result ); } HTH Arjan
Oct 15 2007