[Iterators] Change in transform_iterator from 1.31 to 1.32?
We have a class that contains a std::map. This class wants to provide
its clients with iterators over just the values in the map, hiding the
fact that there's a map under the covers at all. transform_iterator
seems like just the ticket, and with Boost 1.31 we used these methods:
typedef std::map
Nat Goodspeed wrote:
We have a class that contains a std::map. This class wants to provide its clients with iterators over just the values in the map, hiding the fact that there's a map under the covers at all. transform_iterator seems like just the ticket, and with Boost 1.31 we used these methods:
typedef std::map
MapType; typedef boost::transform_iterator< boost::function
, MapType::const_iterator const_iterator;
const_iterator begin() const { return boost::make_transform_iterator(mymap.begin(), boost::bind(&MapType::value_type::second, _1)); }
const_iterator end() const { return boost::make_transform_iterator(mymap.end(), boost::bind(&MapType::value_type::second, _1)); }
The above compiled cleanly, except when it caused a compiler ICE, and the instances that compile seem to run okay.
Now we're trying to upgrade to Boost 1.32 -- I know, a little late in the 1.32 lifespan. The same code now produces an ominous warning (full text at end of message):
c:/videobranch\boost\boost\function\function_template.hpp(111) : warning C4172: returning address of local variable or temporary
When it finally gets around to mentioning a line number in our own source code, the indicated line is the return statement in the above begin() method.
The change that's breaking your code is (unfortunately) in boost::bind, not
in transform_iterator. In 1.31, boost::bind(&MapType::value_type::second,
_1) returns a reference. In 1.32, the same construct returns by value.
You can change
boost::function
"Peter Dimov"
c:/videobranch\boost\boost\function\function_template.hpp(111) : warning C4172: returning address of local variable or temporary
The first thing for you to know is that vc7.1 gave that warning erroneously in many cases. In this case, however, it seems correct.
When it finally gets around to mentioning a line number in our own source code, the indicated line is the return statement in the above begin() method.
The change that's breaking your code is (unfortunately) in boost::bind, not in transform_iterator. In 1.31, boost::bind(&MapType::value_type::second, _1) returns a reference. In 1.32, the same construct returns by value.
If Nat were using the actual type of the bind expression as the first argument to transform_iterator, this wouldn't be a problem (except -- not sure if you care -- that it would be returned by value from the iterator). Presumably, the bind object has an appropriate non-reference nested result_type. Nat, what you are doing looks _really_ inefficient. The result of make_transform_iterator is some iterator type that's very different from, but convertible to, your const_iterator type. Going through that extra layer using boost::function means you are doing a lot of extra copying -- and potentially, dynamic memory allocation -- whenever you ask for an iterator. HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com
Nat Goodspeed writes:
We have a class that contains a std::map. This class wants to provide its clients with iterators over just the values in the map, hiding the fact that there's a map under the covers at all. transform_iterator seems like just the ticket, and with Boost 1.31 we used these methods:
[...]
The reason I'm concerned is that when compiled with Boost 1.32, our program suffers mysterious crashes that it did not when compiled with Boost 1.31. :-(
See http://article.gmane.org/gmane.comp.lib.boost.devel/124603. -- Aleksey Gurtovoy MetaCommunications Engineering
participants (4)
-
Aleksey Gurtovoy
-
David Abrahams
-
Nat Goodspeed
-
Peter Dimov