$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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