Topic: Constness of hint in insert method


Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1999/06/25
Raw View
Dave Abrahams <abrahams@mediaone.net> wrote:

: Here's a simple and typical example problem which is currently very
: difficult to solve without the proposed change:

: Wrap a standard container C in a class W which allows clients to find and
: read (but not modify) a subrange of (C.begin(), C.end()]. The only
: modification clients are allowed to make to elements in this subrange is to
: erase them from C through the use of a member function of W.

I think I see your point.

template <class T> class W {
   private :
      std::list<T> data;
   public :
      list<T>::const_iterator begin () const { return data.begin(); }
      list<T>::const_iterator end () const { return data.end(); }
      list<T>::const_iterator erase (list<T>::const_iterator it) {
         list<T>::iterator t(data.begin());
         list<T>::const_iterator u(t);
         advance(t, distance(u, it));
         return data.erase(t);
         }
   };

Not only unpleasant but inefficient.  If list<>::erase accepted a
const_iterator, that function would be

         return data.erase(it);

Since the iterators are implementation defined, there is no way for
a user to convert a const_iterator to an iterator.  OTOH, the
container implementator can do it easily.

John
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Dave Abrahams <abrahams@mediaone.net>
Date: 1999/06/18
Raw View
In article <Ddda3.24749$uk.406898@newscene.newscene.com> ,
jpotter@falcon.lhup.edu (John Potter) wrote:

> : Should this be a defect report?

Yes, it definitely should. In fact this problem is symptomatic of a problem
which appears throughout the STL container interfaces.

>: Does anyone know why the C++ spec is not written this way?

I suspect it was a conceptual problem on the part of the designers of the
STL. The generalized problem looks like this: all functions which modify
containers have been (erroneously) specified to accept only non-const
iterators in their parameter lists, whereas it is the constness of the
container object *itself* which is important.

In fact, all non-const iterator parameters to container member functions
should be changed to accept const_iterator parameters.

I tried to get this on the library issues list for the last meeting before
standardization, but at such a late date I had to pick my battles, and
standard library exception-safety seemed like a more pressing issue at the
time ;)

Here's a simple and typical example problem which is currently very
difficult to solve without the proposed change:

Wrap a standard container C in a class W which allows clients to find and
read (but not modify) a subrange of (C.begin(), C.end()]. The only
modification clients are allowed to make to elements in this subrange is to
erase them from C through the use of a member function of W.

-Dave
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1999/06/17
Raw View
"Ed Brey" <brey@afd.mke.etn.com> wrote:

: Does anyone know why the C++ spec is not written this way?

I guess not. <g>



Author: "Ed Brey" <brey@afd.mke.etn.com>
Date: 1999/06/11
Raw View
For associative containers, the hint parameter to the hinted insert method
is a non-const iterator.  It seems to me that for associative containers, it
should be a const_iterator, since the insert method does not change what the
hint iterator is pointing to.

Additionally, it allows for safer programming.  For instance, given a
multimap<int,char> for which there are many different ints, but only a few
different chars, the multimap might contain:

2,'A'
3,'A'
3,'B'

Suppose you wanted to insert 3,A only if it didn't already exist.  You might
want to say:

pair<M::const_iterator, const_iterator> itit = m.equal_range(3);
M::const_iterator hint = itit.first;
for (;;++itit.first)
    if (itit.first == itit.second)
       m.insert(hint, make_pair(3, 'A'));
    else if (itit.first->second == 'A')
        break;

Using const_iterator is helpful for preventing mistakes.  For example, it
would catch at compiler time the error that would exist if the last two
lines were:

    else if (itit.first->second = 'A')
        break;

Does anyone know why the C++ spec is not written this way?  Should this be a
defect report?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]