Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2007-07-19 19:36:55


on Thu Jul 19 2007, Manuel Holtgrewe <purestorm-AT-ggnore.net> wrote:

> Hi,
>
> I have a problem using the Boost.Iterators library correctly. The
> following minimal example does neither compile with GCC 4.2 nor with
> a current ICC 10.0 version.
>
> It seems that putting a boost::transform_iterator inside a pair makes
> it impossible to retrieve its value again using std::iterator_traits.

That's not the conclusion I would draw from what you show below.

> I would welcome a proposal how to resolve the problem. I get the bug
> when using transform_iterator together with the MCSTL (Multi Core
> STL) and thus cannot change the internals. I would thus like to know
> if and how I can make the following work without touching the inner()
> and outer() functions themselves since I do not have the possibility
> to change the library code itself.
>
> Am I using boost::transform_iterator incorrectly?

I think so.

> Kind Regards,
>
> Manuel
>
> == File Source ==
>
> #include <iostream>
> #include <vector>
> #include <functional>
>
> #include <boost/iterator/transform_iterator.hpp>
>
> class plus_two : public std::unary_function<int, int> {
> public:
> int operator()(int x) const {
> return x + 2;
> }
> };
>
> template <class Pair>
> void inner(Pair pair) {
> typedef typename Pair::first_type Iterator;
> typedef typename std::iterator_traits<Iterator>::value_type T;
>
> Pair p = pair;
>
> T *x = &p.first[0];

OK, first of all, if p.first is a transform_iterator, then the result
of p.first[0] is not a reference as you might expect
It's a temporary proxy object (see
http://www.boost.org/libs/iterator/doc/iterator_facade.html#operator),
which explains this warning and error:

> conflict.cpp: In function 'void inner(Pair) [with Pair =
> std::pair<boost::transform_iterator<plus_two, int*,
> boost::use_default, boost::use_default>,
> boost::transform_iterator<plus_two, int*, boost::use_default,
> boost::use_default> >]':
> conflict.cpp:21: warning: taking address of temporary
> conflict.cpp:21: error: cannot convert
> 'boost::detail::operator_brackets_proxy<boost::transform_iterator<plus_t
> wo, int*, boost::use_default, boost::use_default> >*' to 'int*' in
> initialization

Secondly, even if it could be a reference, (or you used the
otherwise-equivalent &*p.first) your transform function returns by
value, not by reference. So that too would be a reference to a
temporary.

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
The Astoria Seminar ==> http://www.astoriaseminar.com

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