Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2004-12-01 19:02:42


Vladimir Prus wrote:
> Eric,
> I've some questions about BOOST_FOREACH (which is pretty cool, BTW).

Thanks!

>
> 1. Is it possible to use typeof on gcc, to avoid any possible overhead? While
> you've posted some results which show that gcc generally can optimise it very
> well, I'd like to be 100% sure). Something like:
>
> #define FOR_EACH(var, container) \
> for(typeof(container.begin()) _for_each_i = container.begin(),\
> _for_each_e = container.end();\
> _for_each_i != _for_each_e; ++_for_each_i)\
> if(bool _for_each_continue = false) {}\
> else\
> for(var = *_for_each_i; !_for_each_continue; _for_each_continue=true)
>
> which works perfectly for me.

It's probably possible, but there are a couple of subtle issues that
would need to be dealt with. First, BOOST_FOREACH should be extensible,
meaning, there should be a well-defined way to "hook" BOOST_FOREACH to
get it to enumerate other user-defined collections. The mechanism to
hook BOOST_FOREACH should be the same regardless of whether
BOOST_FOREACH is implemented with native typeof or not. Second,
BOOST_FOREACH should work out of the box with arrays, null-terminated
strings and iterator pairs in addition to STL(-like) containers. The
second should be easy, but the first would require some careful design.
Considering that BOOST_FOREACH is pretty optimal already, I'm not
convinced it's worth it.

Also, note that the above version is buggy because it doesn't handle
break statements correctly.

>
> 2. Any chance that
>
> BOOST_FOREACH((pair<int, int> p), container)
>
> will work? I don't know how to make it work without require paranthethis in
> all cases, but maybe there's a smart trick.
>

I don't think so, sorry. You would have to use a typedef, as in:

     typedef pair<int,int> pair_int;
     BOOST_FOREACH( pair_int p, container )

> 3. Is it possible that you place this to sandbox, for easier access?
>

Done. It's at boost-sandbox/boost/foreach.hpp. You'll notice that it's a
reimplementation. This version only evaluates the container expression
once, so you can use complicated expressions as the second parameter.
This makes BOOST_FOREACH very useful with filtered ranges, where the
element type is simple, but the type of the "container" is very complicated.

I'll probably need some docs and tests at some point. It's really quite
useful and safe now(*) so perhaps I'll actually put it up for review soon.

(*) There is one outstanding problem that I have not yet solved. I think
it's unsolvable in the current language, but I hope I'm wrong. The
current implementation does the wrong thing when the container
expression is a const-qualified rvalue STL container. It uses the rules
for binding to reference to distinguish lvalues from rvalues, storing
references for lvalues and copies for rvalues. Const-qualified rvalues
screw this up, so the following crashes:

   std::vector<int> const get_vector();
   ...
   BOOST_FOREACH( int i, get_vector() )

I'm not sure how serious this problem is. If anyone knows of a foolproof
way to distinguish lvalues from rvalues, I'm all ears.

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk