Boost logo

Boost Users :

Subject: Re: [Boost-users] Limitations / Flaws with transformed_range
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2011-07-19 19:10:40


> > I don't think this "operator|" - which lives in the boost::range_detail
> > namespace (note the "detail") - is meant to be specialized by users.
>
> On the contrary. It's not specialized, but overloaded, and the instructions say to do
> exactly that. In particular,
> <http://www.boost.org/doc/libs/1_46_1/libs/range/doc/html/range/reference/extending/method_3/method_3_1.html>
> "Implement a Rage Adaptor without arguments".

I'm sorry, I misread your code. I saw the return type was transformed_range and so
I thought you are somehow trying to specialize the "transformed" adaptor's operator|
to behave differently when you do "my_range | transformed(ASCII_lower())".

Looking at it again, it seems what you are really trying to do is write your own
adaptor "ASCII_lowered" or something similar that would be used as
"my_range | ASCII_lowered" (which is precisely what I was suggesting).

Now, regarding your problem (which I now understand):

> template< class Range >
> inline transformed_range<ASCII_lower,const Range>
> operator|( const Range& r, const ASCII_lower_forwarder )
> {
> return transformed_range<ASCII_lower,const Range>(
> ASCII_lower(), // The underlying transform iterators wants this
> internal::src_prep(typename std::tr1::is_pointer<Range>::type() ,r) //
> "source" style argument processing
> );
> }

As you discovered, returning transformed_range<ASCII_lower, const Range>
won't work because src_prep() does not return "const Range", it returns
something else.

I see 3 solutions:

1) Write a metafunction "src_prep_result" that computes the return type
of src_prep() on input Range, and the return:

transformed_range<ASCII_lower, typename src_prep_result<Range>::type>

2) [C++0x only] Use decltype to figure out what src_prep returns, i.e.
return:

transformed_range<ASCII_lower, decltype(internal::src_prep(typename std::tr1::is_pointer<Range>::type(), r))>

If you can't use C++0x, you may want to try the BOOST_TYPEOF() macro
which emulates it. I'm not sure how well it works.

3) If, as you say, the iterator types of "Range" and the return type of
src_prep() are the same, you can return an iterator_range, as follows
(untested):

template <typename Range>
iterator_range<typename range_iterator<Range>::type> convert_to_iterator_range(const Range& r)
{
    return iterator_range<typename range_iterator<Range>::type>(begin(r), end(r));
}

template< class Range >
inline transformed_range<ASCII_lower, const iterator_range<typename range_iterator<Range>::type> >
operator|( const Range& r, const ASCII_lower_forwarder )
{
    return transformed_range<ASCII_lower, const iterator_range<typename range_iterator<Range>::type> >(
        ASCII_lower(),
        convert_to_iterator_range(internal::src_prep(typename std::tr1::is_pointer<Range>::type(), r))
    );
}

Regards,
Nate.
                                               


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net