The Artima Developer Community
Sponsored Link

Articles Forum
Conditional Love: FOREACH Redux

7 replies on 1 page. Most recent reply: Apr 2, 2005 10:59 AM by Eric Niebler

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 7 replies on 1 page
Chuck Allison

Posts: 63
Nickname: cda
Registered: Feb, 2003

Conditional Love: FOREACH Redux Posted: Feb 18, 2005 6:00 AM
Reply to this message Reply
Advertisement
Eric Niebler shows how to use the subtleties of the conditional operator, coupled with templates and macro magic, to create a robust iteration construct.

http://www.artima.com/cppsource/foreach.html


Bruno Martínez

Posts: 2
Nickname: br1
Registered: Nov, 2003

Re: Conditional Love: FOREACH Redux Posted: Feb 18, 2005 6:00 AM
Reply to this message Reply
I really had a great time reading this article. I just loved the cleverness of using the ternary operator to get the type and pass it to auto_any functions. This is one of those articles that just amaze you, because you already knew how the parts work but it would never have ocurred you to combine them.

The part about rvalue detection isn't that great, though, as the you knew it part doesn't exist.

indranil banerjee

Posts: 38
Nickname: indranil
Registered: Nov, 2004

Re: Conditional Love: FOREACH Redux Posted: Feb 18, 2005 1:08 PM
Reply to this message Reply
Awesome article, FOREACH is the kind of utility that can massively improve the quality of C++ code and it is amazing to see how it is implemented.

I decided to delve deeper and looked at foreach.hpp. I noticed a number of difference from the article, I guess these were mainly for exposition purposes.

BOOST_FOREACH doesnt use boost::variant, it has a mini roll-your-own simple_variant class, any reason why? Also simple_variant doesnt have an assignment operator, i guess the default implementation is safe here.

Things like rvalue_probe and auto_any could be useful in other contexts, are they used elsewhere in Boost or the wider world? If so should they be factored out into their own headers?

Finally is it safe to nest two BOOST_FOREACH macros?

Eric Niebler

Posts: 14
Nickname: ericne
Registered: Feb, 2005

Re: Conditional Love: FOREACH Redux Posted: Feb 18, 2005 1:40 PM
Reply to this message Reply
> Awesome article

Thanks!

> BOOST_FOREACH doesnt use boost::variant, it has a mini
> roll-your-own simple_variant class, any reason why?

I found it was hurting compile times. It's a bigger hammer than I really need in this case.

> Also simple_variant doesnt have an assignment operator,
> i guess the default implementation is safe here.

It's not! But I never assign one of these guys. I should make the assignment operator private, thanks!

> Things like rvalue_probe and auto_any could be useful
> in other contexts, are they used elsewhere in Boost or
> the wider world? If so should they be factored out into
> their own headers?

I'll factor them out as need requires.

> Finally is it safe to nest two BOOST_FOREACH macros?

You bet!

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

Eric Niebler

Posts: 14
Nickname: ericne
Registered: Feb, 2005

Re: Conditional Love: FOREACH Redux Posted: Feb 21, 2005 1:52 PM
Reply to this message Reply
Incidentally, I have found a simpler formulation of ENCODED_TYPEOF that doesn't require type2type or anytype. Consider:

template<class T>
T const * encode_type( T const & t ) {
return 0;
}

#define ENCODED_TYPEOF( expr )\
( true ? 0 : encode_type( expr ) )

This uses the fact that the null pointer constant (0) is implicitly convertible to a pointer of any type. Now, you can use "T const*" as a dummy parameter to functions that need to infer the type T. Not only is this simpler, but it even works on ancient compilers like VC6.

Also, Andrei Alexandrescu has sent me a "perfect" version of the MIN/MAX macros that use the conditional operator trick to avoid reevaluation of their arguments. Very neat stuff! We'll hopefully be posting it soon.

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

martin cohen

Posts: 3
Nickname: mjcohen
Registered: Oct, 2003

Re: Conditional Love: FOREACH Redux Posted: Feb 23, 2005 2:50 PM
Reply to this message Reply
Whew! A lot of nice stuff - I'll have to reread this a few times.

I personally love the conditional operator, and use it a lot in both C and gawk. My "secret" to making nested conditionals understandable is to treat it as being precisely analogous to nested if-then-else statements. An example is


a = (b > 0
? (c/2)
: (g in hoohaa
? (int(h) == h
? (cos(r) <= sin(r)
? tanh(e)
: lngamma(pi)
)
: (2/zeta(e))
)
: (g-1)
)
);


(Hope everything is lined up and balanced - Emacs helps a lot)

Liu WeiPeng

Posts: 4
Nickname: pongba
Registered: Mar, 2005

Re: Conditional Love: FOREACH Redux Posted: Mar 23, 2005 11:50 PM
Reply to this message Reply
Despite of my absolute loving this facility,I wonder if there exists one little pitfall.

It seems to me that the problem raises its ugly head when we use BOOST_FOREACH for some container that contains instances of type like std::string or whatever owns its own resource.

IMO,some classes that hold their own resources will do copy assignment differently as they do "destruction-then-in-place-construction".

Since BOOST_FOREACH uses nested for-statement,the variable in the inner loop will get initialized each time the outer for-loop recurs.Note that I refered to "initialize" instead of "copy-assignment",the former means a destruction followed by a construction,while the latter means merely one copy assignment.

For me,the situation can become really tough when the class gets a optimized copy assignment which can reuse the previously allocated storage to hold the new stuffs,while its destructor *delete* the storage and its constructor *re-require* them.

e.g.

for(string s = ...;...;...)
{
s = ...; // copy assignment , the lifetime of s lasts until the for-statement ends
}

// BOOST_FOREACH's implementation
for(...)
{
for(string s = ...;...;...) // get re-constructed each time the outer loop recurs
{
}
}

Surely,I know that there should be some caveat when using BOOST_FOREACH,one of which should refer to this.But I read through the document and see nothing about that,so I wonder if it's an oversight,or "not-a-problem",or merely my misunderstand?

Anyway,thank you for doing such an excellent job,it's really usefull and amazing.

Eric Niebler

Posts: 14
Nickname: ericne
Registered: Feb, 2005

Re: Conditional Love: FOREACH Redux Posted: Apr 2, 2005 10:59 AM
Reply to this message Reply
liu wei peng, you are correct, there are scenarios where BOOST_FOREACH could cause an extra allocation over a hand-coded loop. Funny, that hadn't even occured to me. I don't see a way to fix it while allowing BOOST_FOREACH to continue working with references, because the reference simply must be rebound each time:


for(..;..;..)
for(int &i = ..;..;..)


This is certainly a trade-off, though, and I see your point. You can avoid the construction/destruction issue if you use BOOST_FOREACH like this:


std:::string str;
BOOST_FOREACH(str, vector_of_string)
..


There should probably be a note about this in BOOST_FOREACH's documentation.

Thanks for raising the issue.

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

Flat View: This topic has 7 replies on 1 page
Topic: What's Your Address? Previous Topic   Next Topic Topic: Reducing Preprocessor Namespace Pollution


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us