Boost logo

Boost Users :

Subject: Re: [Boost-users] [iterator] Automatic definition of transform_iterator reference_type
From: Jeff Flinn (TriumphSprint2000_at_[hidden])
Date: 2009-10-22 09:09:23


Sebastian Theophil wrote:
> [Posted once again with better subject]
>
> I've encountered a problem when using boost::mem_fn in
> transform_iterators. In the attached example, I've chained two
> transform_iterators. The first iterator returns an Obj by value and the
> second extracts a member of the temporary object. The example shows that
> the return value is not quite what is expected.
>
> boost::mem_fn(&Obj::m_member) returns an int const&. The
> transform_iterator uses the return value of the UnaryFunction template
> parameter to initialize his value_type. In the given example, this logic
> seems too simple. At least if the UnaryFunction is of type
> boost::_mfi::dm the transform_iterator could do better:
>
> If Reference is boost::use_default
> If UnaryFunction is boost::_mfi::dm
> && Iterator::value_type is not a reference itself
> reference = boost::remove_reference(
> result_of(UnaryFunction) )
> Else
> reference = result_of(UnaryFunction)
> Else
> reference = Reference
>
> Is this too much of a special case to fix it in the transform_iterator?
> The same logic would apply to all (unknown) functors that returned
> references to member variables. In general, the transform_iterator can
> probably not decide if a reference returned from a UnaryFunction will
> cease to exist when the temporary is destroyed. It could have been a
> global object. On the other hand, transform_iterators should work
> correctly if only boost objects are used, shouldn't they?
>
> I'd like to hear what you think,
> Sebastian
>
>
> #include "boost/iterator/transform_iterator.hpp"
> #include <vector>
>
> struct Obj {
> Obj(int n) : m_member(n) {}
> Obj(Obj const& obj) : m_member(obj.m_member) {}
> ~Obj() { m_member=INT_MIN; }
>
> int m_member;
> };
>
> static Obj GetObjByValue( int n ) { return Obj(n); }
>
> void main() {
> std::vector<int> v(1, 5);
>
> int n=*boost::make_transform_iterator(
> boost::make_transform_iterator( v.begin(), GetObjByValue
> ),
> boost::mem_fn(&Obj::m_member)
> );
> _ASSERT(n==INT_MIN);
> }

How about composing the function rather than the iterator ala:(untested)

int n = *make_transform_iterator
         ( v.begin()
         , bind( &Obj::m_member, bind(GetObjByValue, _1));

Jeff


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