Boost logo

Boost Users :

Subject: [Boost-users] Limitations / Flaws with transformed_range
From: John M. Dlugosz (mpbecey7gu_at_[hidden])
Date: 2011-07-19 04:19:47


I've already noted that the "transformed_range", the class behind
boost::adaptors::transform, is not using result_of as documented but seems to be simply
looking for result_type, period.

I've found another issue, and I consider it a "flaw" because it is a Limitation due to
oversight or an artificial restriction, and the deeper workings should handle these cases
just fine. Let me explain in detail:

The
         template< class F, class R >
         struct transformed_range :

takes two arguments. The R argument is used for two purposes. It gives the iterator type
that will be held, via range_iterator<R>::type. It also gives the exact type of the
argument expected by the constructor.

Now here is an example from my experiments / work-in-progress:

     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
           );
        }

The src_prep is similar to the supplied is_literal, and used for the same purpose. It
will package a primitive array as a iterator_range, handing string literals and primitive
array objects in the way I intend with respect to nul terminators. It differs from
is_literal in several ways, but the idea is the same.

Now I don't have to do anything to the Range parameter passed as the type argument to
transformed_range, because even when I change the type of the massaged argument, it still
has the same underlying iterator type. After all, it gets the iterators from the original
range thing passed in.

But, the massaged value of r is rejected by the constructor, because it has a different
type. It doesn't need to be the same type! It has the same underlying iterator type and
could be assigned to it, but the constructor is too strict.

It would be a simple matter of passing another template argument to the constructor, as is
commonly done with constructors or assignment, and take anything that "works" in that
boost::begin and boost::end returns something that can be used to initialize the
range_iterator.

Copying the class to my own code and changing the constructor to:

         template <typename R2>
             transformed_range( F f, R2& r )
                 : base( boost::make_transform_iterator( boost::begin(r), f ),
                         boost::make_transform_iterator( boost::end(r), f ) )

indeed makes it acceptable to the compiler. (At this point I also noticed that _some_ of
the types within the class are qualified by boost::, but not all of them. I know that
functions are qualified to prevent argument-dependant lookup, but it is odd that some of
the types (or names used in other context) are qualified and sometimes they are not.)


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