Boost logo

Boost :

Subject: Re: [boost] [iterator] [property_map] Enhancement proposals
From: Louis Dionne (louis.dionne92_at_[hidden])
Date: 2012-10-13 19:25:51


Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung <at> gmail.com> writes:

> > Accepting any iterator that is convertible to the wrapped iterator is nice
> > if it is not dangerous because it allows to do this:
> >
> > typedef chained_output_iterator<Functor1,
> > chained_output_iterator<Functor2,
> > std::back_insert_iterator<std::vector<T>>>> OutIter;
> > // Then, if Functor1 and Functor2 are default constructible:
> > std::vector<T> vec;
> > OutIter result(std::back_inserter(vec));
> >
> > If the constructor only takes an instance of the wrapped iterator, the
> > following must be done, which could be annoying if one creates a long
> > chain:
> >
> > typedef chained_output_iterator<Functor2,
> > std::back_insert_iterator<std::vector<T>>> Chain;
> > typedef chained_output_iterator<Functor1, Chain> OutIter;
> > std::vector<T> vec;
> > OutIter result(Chain(std::back_inserter(vec)));
> >
> > So I would advocate in favor of keeping the initial implementation for the
> > first two constructors, unless I am missing something.
> >
>
> Wouldn't the first block of code above not compile regardless of whether
> the unary constructor is a template constrained by enable_if<
> is_convertible > or takes the wrapped iterator directly? The result of
> std::back_inserter(vec) is not convertible to the intermediate
> chained_output_iterator in either case.

Yes, the first block of code compiles. Let's say we have:

    typedef std::back_insert_iterator<std::vector<T> > Third;
    typedef chained_output_iterator<Functor2, Third> Second;
    typedef chained_output_iterator<Functor1, Second> First;

Third is convertible to Second:

    template <typename Iterator>
    Second(Iterator const& iterator,
           typename enable_if_convertible<Iterator, WrappedIter>::type* =0);

with [Iterator = Third]
     [WrappedIter = Third] (because Second::WrappedIter == Third)

By the same mechanism, Second is convertible to First. Now, let's see why we
can construct a First from a Third:

    Third third;
    First first(third); // This calls the template unary constructor below.

    First(Third const& iterator,
          typename enable_if_convertible<Third, Second>::type* =0)
        : out_(iterator) // This calls the template unary constructor below.
    { }

    Second(Third const& iterator,
           typename enable_if_convertible<Third, Third>::type* = 0)
        : out_(iterator) // This calls the constructor of Third, which is
    { } // std::back_insert_iterator.

I hope my explanation is clear enough. There is also a unit test for this on
the master branch.

> If you had the following chained_output_iterator constructor:
>
> template< class G, class J >
> chained_output_iterator(chained_output_iterator<G,J>,
> typename enable_if_c< mpl::and<
> is_convertible<H,G>,
> is_convertible<J,I>
> >::value >::type * = 0);
>
> Oops, now chained_output_iterator< F, derived_t * > is convertible to
> chained_output_iterator< F, base_t * >. is_convertible<J,I> is too loose
> (admittedly, there are many iterator contexts where you simply cannot
> prevent the derived_t * -> base_t * conversion, but if you can prevent it,
> you should).
>
> Presently, there is no such converting constructor, and I don't yet see a
> need for one.

Thanks for the explanation. I replaced the loose copy constructor by the one
generated by the compiler.

> Best (i.e., least work for me) would be to provide the header, the unit
> test, any patches to the present Boost.Iterator documentation, and a
> contract signed in blood that you'll support this for life. Well, okay,
> I'll take 3 out of 4 :)
>
> Where you make the files available doesn't matter too much, just as long as
> I can easily grab them when ready. I guess the official route is to create
> a feature enhancement request trac ticket with the files attached.

Alright. I'll create a ticket when everything is ready. Since it's not
getting in before at least 1.53, I'll take my time and do something good.

Thanks!

Louis Dionne


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