Boost logo

Boost :

Subject: Re: [boost] [iterator] Is there general const_iterator adaptor?
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2013-04-30 00:31:09


On Mon, Apr 29, 2013 at 10:54 AM, TONGARI <tongari95_at_[hidden]> wrote:

> 2013/4/30 Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung_at_[hidden]>
>
> > On Sun, Apr 28, 2013 at 6:38 AM, Philipp Moeller <
> > philipp.moeller_at_[hidden]> wrote:
> >
> > > TONGARI <tongari95_at_[hidden]> writes:
> > >
> > > > Hi folks,
> > > >
> > > > I wonder if there's a general const_iterator adaptor that transforms
> > any
> > > > iterator to a const one:
> > > >
> > > > template<class Iterator>
> > > > struct const_iterator
> > > > : iterator_adaptor
> > > > <
> > > > const_iterator<Iterator>, Iterator
> > > > , typename iterator_value<Iterator>::type const
> > > > >
> > > > {
> > > > const_iterator() {}
> > > >
> > > > const_iterator(Iterator const& base)
> > > > : const_iterator::iterator_adaptor_(base)
> > > > {}
> > > > };
> > > >
> > > > Which is simple but handy for use in that we don't have to make 2
> > > versions
> > > > for both const & non-const iterators each time we make a container.
> > > >
> > > > Does Boost offer this which I missed somewhere, or would you think
> > it's a
> > > > good idea to add?
> > >
> > > If you look at the documentation of iterator_facade you will see that
> it
> > > already shows how to just write one version of the iterator and get a
> > > const version for free: pass a `const T` as the second argument of
> > > iterator_face and it should work.
> > >
> >
> > I think this is typically essentially what you want to do. Define a
> helper
> > template like
> >
> > template< class T > struct iterator_helper { typedef /*...*/ type; };
> >
> > then
> >
> > typedef iterator_helper< value_type >::type iterator;
> > typedef iterator_helper< value_type const >::type const_iterator;
> >
> > If that isn't possible or convenient, your iterator and const_iterator
> are
> > probably sufficiently different that defining them separately will be
> > acceptable.
>

I still think this is preferable.

> The typical problem with your const_iterator adaptor above is that it
> > likely can't be constructed in a const context, since you wouldn't be
> able
> > to obtain an (mutating) iterator (unless you do const_cast contortions).
> >
>
> True, that's what I did exactly (i.e. const_cast).
>
>
> > Also, shouldn't the reference type passed to iterator_adaptor also need
> to
> > be "constified"? Which gets complicated when the reference type is a
> proxy
> > reference...
> >
>
> Haven't considered that, so the non-intrusive const_iterator may not be
> general enough, but what I looked for was something that works for most
> cases.
>
> We could have that for our 'detail' usage, but if it's common enough, then
> it might be nice to have it in public.
>
> So would you suggest such an adaptor for those simple cases no more than
> adding the const?
>

A utility that only works for simple cases inevitably evolves and
complicates to handle the more complex cases as feature requests come
through :/ And, like I hinted at above, I don't think it can be made to
work with proxy references without adding a hook to "constify" the proxy
reference. I'm not sure the complication justifies its existence. There's
also mild safety issues, in that calling base() on the const_iterator gives
you the underlying (mutating) iterator.

So I would hesitate to add this myself under the Iterator library, but,
hey, maybe you can convince someone else :)

Maybe the discussion would facilitated by providing a concrete use case,
as, in my experience, I haven't been compelled to create such an adaptor.

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk