foreach question

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; }

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; }
See this thread http://thread.gmane.org/gmane.comp.lib.boost.user/54162 And the resulting Trac ticket: https://svn.boost.org/trac/boost/ticket/3469 for a essentially negative answer.

Pete Bartlett <pete <at> pcbartlett.com> writes:
See this thread http://thread.gmane.org/gmane.comp.lib.boost.user/54162 And the resulting Trac ticket: https://svn.boost.org/trac/boost/ticket/3469
for a essentially negative answer.
Personally, I like the answer in that thread that said: #define INDEX_FOREACH(index,a,b) \ for(unsigned int index = static_cast<unsigned int>(-1); \ index == static_cast<unsigned int>(-1);) \ BOOST_FOREACH(a,b) if(++index,true) The for loop just does a variable declaration in a way that means you won't get bit by using it somewhere that doesn't allow variable declarations. Convoluted but important. Of course, it isn't that generic - it always assumes you want an int index. But then that is what the question said... Jerry

Jerry Jeremiah wrote:
Pete Bartlett <pete <at> pcbartlett.com> writes:
See this thread http://thread.gmane.org/gmane.comp.lib.boost.user/54162 And the resulting Trac ticket: https://svn.boost.org/trac/boost/ticket/3469
for a essentially negative answer.
Personally, I like the answer in that thread that said:
#define INDEX_FOREACH(index,a,b) \ for(unsigned int index = static_cast<unsigned int>(-1); \ index == static_cast<unsigned int>(-1);) \ BOOST_FOREACH(a,b) if(++index,true)
The for loop just does a variable declaration in a way that means you won't get bit by using it somewhere that doesn't allow variable declarations. Convoluted but important.
Of course, it isn't that generic - it always assumes you want an int index. But then that is what the question said...
Jerry
Won't win any beauty contest.

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; }
Using c++0x: auto myrange = make_iterator_range( boost::make_zip_iterator( boost::make_tuple( boost::counting_iterator<size_t>(0), result.begin())), boost::make_zip_iterator( boost::make_tuple( boost::counting_iterator<size_t>(result.size()), result.end()))); BOOST_FOREACH(auto t, myrange) { using boost::tuples::get; H(row, get<0>(t)) = boost::lexical_cast<int>(get<1>(t)); } Which, unfortunately, is quite a bit more verbose and less clear than what you have now. zip iterators and counting iterators are really nice concepts, but they don't make for clear, compact code. And just imagine what that would look like without the type inference provided by c++0x's "auto" keyword. However, the making of the zip iterators for this purpose is such a common idiom in other languages (including Python), and this is easily abstracted into a helper function, that this would be an ideal enhancement to Boost. Something like: template <typename Range> auto make_counting_range(Range& range, size_t start = 0) -> decltype(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))))) { 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)))); } Which 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.) Rob
participants (4)
-
Jerry Jeremiah
-
Neal Becker
-
Pete Bartlett
-
Rob Riggs