
Rob Riggs wrote:
On 10/15/2010 12:27 PM, Neal Becker wrote:
The following loop iterates over strings in result (which comes from boost::split). Is there a way to include the integer enumerator 'col' into the FOREACH loop?
In python that would be spelled for col,s in enumerate (result): ...
int col = 0; BOOST_FOREACH (std::string s, result) { H(row, col) = boost::lexical_cast<int> (s); ++col; }
Something like:
template <typename Range> auto make_counting_range(Range& range, size_t start = 0 [..]
would then give you:
BOOST_FOREACH(auto t, make_counting_range(result)) { using boost::tuples::get; H(row, get<0>(t)) = boost::lexical_cast<int>(get<1>(t)); }
(Compiled with GCC 4.4.)
Even without C++0x, you can wrap this up into a reasonable interface to get e.g. std::vector<std::string> data = boost::assign::list_of("foo")("bar")("baz"); BOOST_INDEXED_EACH( std::size_t i , std::string const& s , data ) std::cout << "\n" << i << " " << s; if you tinker a little bit with BOOST_FOREACH internals - see code below, compiled on vc10 with Boost.ForEach code as in 1.43. However for the same reasons that BOOST_REVERSE_FOREACH exists (rather than just using BOOST_FOREACH( ... , make_reverse_range(r) ) - see http://lists.boost.org/boost-users/2007/07/29101.php ) this approach doesn't play well with rvalue ranges. Instead you'd have to duplicate the guts of FOREACH, as Eric did for REVERSE_FOREACH, to get a library-quality version. Pete #include <boost/range/begin.hpp> #include <boost/range/end.hpp> #include <boost/range/distance.hpp> #include <boost/range/iterator_range.hpp> #include <boost/iterator/zip_iterator.hpp> #include <boost/iterator/counting_iterator.hpp> template< typename Range > struct indexed_range { typedef boost::counting_iterator<std::size_t> it0_type; typedef typename boost::range_iterator< Range >::type it1_type; typedef boost::tuple< it0_type , it1_type > tuple_type; typedef boost::zip_iterator< tuple_type > zip_type; typedef boost::iterator_range< zip_type > type; }; template< typename Range > typename indexed_range<Range>::type make_indexed_range(Range& range , std::size_t start = 0) { return make_iterator_range( boost::make_zip_iterator( boost::make_tuple( boost::counting_iterator<size_t>(start), boost::begin(range))), boost::make_zip_iterator( boost::make_tuple( boost::counting_iterator<size_t>( boost::distance(range) + start), boost::end(range)))); } #include <boost/foreach.hpp> #define BOOST_INDEXED_EACH_IMPL(VAR1, VAR2 , COL) \ BOOST_FOREACH_PREAMBLE() \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else \ if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) {} else \ for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \ BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \ BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \ if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) {} else \ for (VAR1 = boost::tuples::get<0>( BOOST_FOREACH_DEREF(COL) ); !BOOST_FOREACH_ID(_foreach_continue);)\ for(VAR2 = boost::tuples::get<1>( BOOST_FOREACH_DEREF(COL) ); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true) #define BOOST_INDEXED_EACH(VAR1,VAR2,COL) BOOST_INDEXED_EACH_IMPL(VAR1,VAR2,make_indexed_range(COL)) //test scaffolding #include <vector> #include <iostream> #include <boost/assign/list_of.hpp> int main() { std::vector<std::string> data = boost::assign::list_of("foo")("bar")("baz"); BOOST_INDEXED_EACH( std::size_t i , std::string s , data ) std::cout << "\n" << i << " " << s; std::cout << "\n\n"; return 0; }