Boost logo

Boost :

Subject: Re: [boost] [Range] Range adaptor approach for temporary range lifetime issue
From: Michel Morin (mimomorin_at_[hidden])
Date: 2012-06-18 06:05:50


Neil Groves wrote:
> Thank you ever so much for taking the time to implement your suggestion.
> I will make sure I review this code sometime this week. I'm sure that if
> there are no breaking changes and no gotchas that we can get this into the
> trunk soon.

Thanks for your response, Neil.

[Some gotchas in the implementation]:
* C++11 features (rvalue references and decltype) are used.

* When applying range adaptors in `moved_range`,
a moved container is evaluated as **const lvalue reference**.
(This is because the implementation uses `boost::fusion::accumulate`
to apply range adaptors.)

* The pipe operator of an rvalue `moved_range` has higher priority than
the pipe operators for all other range adaptors (e.g. `reverse_forwarder`)
in overload resolution:

    template <typename Adaptor>
    moved_range<Container, typename meta::push_back<Adaptors, Adaptor>::type>
    operator|(moved_range<Container, Adaptors>&& rng, Adaptor const& adpt);

    template<typename Range>
    reversed_range<Range>
    operator|(Range& rng, reverse_forwarder);

So, when adding rvalue overloading to range adaptors in the future,
we need to avoid ambiguity on overload resolution for the pipe operator.
Suppose we are adding rvalue overloading for `reverse_forwarder`:

    template<typename Range>
    reversed_range<Range>
    operator|(Range&& rng, reverse_forwarder);

This results in compiler errors due to ambiguity.
To avoid ambiguity, we need to lower its priority in overload resolution:

    template<typename Range, typename Adaptor>
    typename boost::enable_if<
        boost::is_same<Adaptor, reverse_forwarder>
      , reversed_range<Range>
>::type
    operator|(Range&& rng, Adaptor);

Or just SFINAE out `moved_range`:

    template<typename Range>
    typename boost::disable_if<
        is_moved_range<Range>
      , reversed_range<Range>
>::type
    operator|(Range&& rng, reverse_forwarder);

[Not yet implemented in the current implementation]:
* #ifndef'ing the code using `BOOST_NO_RVALUE_REFERENCES` and
`BOOST_NO_DECLTYPE`.

* Don't return `moved_range`, if the input to the pipe operator of
`moved_forwarder` is `iterator_range`.

* Built-in array support.

* Add specialization for `moved_range<Range, boost::fusion::vector<> >`
to reduce its space overhead.

Regards,
Michel


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