At 11:06 AM 6/21/2008, you wrote:
Hi,
This is probably a very newbie question. I'd like to iterate through the
values of a std::map. I searched through the archives, and found this
thread on this mailing list about it:
http://lists.boost.org/boost-users/2007/11/32374.php
Unfortunately I can't put the partial recommendations together from that
thread to work for me. While this is most probably due to my lack of
experience with boost, can someone point to a sort-of complete usage
solution to this question? Would be really appreciated.
Here are two solutions in one. One does the transform_iterator by hand,
the other uses a helper class ("make_view") based on
transform_iterator and iterator_range, included at the end.
"make_view" is based on a suggestion that was on the list a
while back. The former does not use boost::bind because the type must be
passed to transform_iterator and I haven't the energy to figure out what
that type is. If you're hand rolling this for a specific std::map, don't
need the generality, and want to hand iterators back to your client, it
is (IMHO) better to do it with an explitic function (or static method).
"make_view" is what I use when I want something
generic.
# include <map>
# include <boost/foreach.hpp>
# include <iostream>
# include <boost/bind.hpp>
#
include
<boost/iterator/transform_iterator.hpp>
# include <local/make_view.hpp>
typedef std::map<int, std::string> Map;
std::string const& MapValue(Map::value_type const& v) { return
v.second; }
typedef boost::transform_iterator<std::string const&
(*)(Map::value_type const&), Map::const_iterator>
value_iterator;
int main(int argc, char* argv[])
{
Map map;
map.insert(Map::value_type(1, "one"));
map.insert(Map::value_type(2, "two"));
map.insert(Map::value_type(3,
"three"));
// Simple, but requires iteration over the entire
container
BOOST_FOREACH(std::string const& s,
boost::make_view(map, bind(&Map::value_type::second, _1)))
std::cout << s <<
" , ";
std::cout << std::endl;
// More flexible iterators, but need more support
value_iterator spot(map.begin(), &MapValue);
value_iterator limit(map.end(), &MapValue);
while (spot != limit) {
std::cout << *spot
<< " , ";
++spot;
}
return 0;
}
local/make_view.hpp
#
pragma
once
/** @file
Create a transformed view of a range or a
container.
*/
#
include
<boost/iterator/transform_iterator.hpp>
#
include
<boost/range/iterator_range.hpp>
#
include
<boost/range/begin.hpp>
#
include
<boost/range/end.hpp>
#
include
<boost/range/iterator.hpp>
/// Boost
namespace
namespace
boost {
/** Create a transform
view from an iterator pair.
A view is a lazy reference to a sequence, specified
here by @a begin and @a end.
The values in the sequence are transformed on access
by @a transform. This avoids
the expense of allocating a container to hold the
intermediate results.
@return The iterator range.
*/
template
<
typename
I
///< Iterator
type
,
typename
F
///< Functor
type
>
inline
iterator_range<transform_iterator< F, I
> > make_view
( I
const
&
begin
///< Start of source
range
, I
const
&
end
///< End of source
range
, F
const
& transform
///< Transform
functor
)
{
return
make_iterator_range(
make_transform_iterator(begin,
transform),
make_transform_iterator(end,
transform));
}
/** Create a view from
an iterator range.
A view is a lazy reference to a sequence, specified
here by @a begin and @a end.
The values in the sequence are transformed on access
by @a transform. This avoids
the expense of allocating a container to hold the
intermediate results.
@note @a range can be an STL compliant container, in
addition to a Boost iterator range.
@return The new iterator range.
@internal Note that we only support const containers,
because being a view
there's no good way to map any changes back to the
original container.
@internal Boost 1.34.1 requires the use of
range_const_iterator<RANGE>, but
1.35.0 permits the use of range_iterator<RANGE
const>.
*/
template
<
typename
RANGE
///< Range type
,
typename
F
///< Transform
functor type
>
inline
iterator_range< transform_iterator< F,
typename
range_const_iterator< RANGE >::type
> > make_view
( RANGE
const
& range
///< Source
range
, F
const
& transform
///< Transform
functor
)
{
return
make_view(begin(range), end(range),
transform);
}
} // namespace boost