I want my foreach() in Whidbey!

Started by
6 comments, last by GameDev.net 19 years, 2 months ago
Feature Request page We need __typeof() support in unmanaged C++ in order to pull off foreach() for STL containers. It is already implemented as an extension for GCC, but sadly not for Visual Studio. The gcc macro is: #define foreach(i, c) for(typeof(c.begin()) i = c.begin(); i != c.end(); ++i) I recently ran into a case where the typeof() extension would help quite a bit in adding a synchronized/lock-style keyword to C++. I had to introduce an otherwise redundant base class to get around it.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Advertisement
I agree with the addition of typeof support. In this case, however, auto is actually the better solution than typeof. The reuse of auto is, along with typeof, almost definitely going to be in the next C++ standard. The additional use of auto that is proposed allows statements such as:

auto i = c.begin(); // i's type is automatically deduced to be the container's appropriate iterator type


Going back to the foreach macro, you can use auto in place of typeof for a more concise for-initialization-statement.

typeof is more useful for things such as function return types and passing the type of an expression as a template argument.
Sounds good. Isn't typeof() in the new standard? Hopefully they're already planning support, but I'll jump in and sign just in case.


In the meantime:

#define foreach(t, i, c) for(t i = c.begin(); i != c.end(); ++i)

where:
typedef std::list< type >::iterator TI;


Its less elegant for sure and isn't exactly standard, but it doesn't read too bad:

foreach(TI, i, typelist){    // do stuff}


[edit] removed html from snippet.

Heed polymorphic's words. He is wise beyond his height... Hope you're doing well back home Polymorphic.

throw table_exception("(? ???)? ? ???");

Quote:Original post by Ravyne
Heed polymorphic's words. He is wise beyond his height... Hope you're doing well back home Polymorphic.

Har har :p

Thanks.
I'm a fan of BOOST_FOREACH now, actually. I #define'd it to be foreach(), (I live dangerously...when was the last time you defined a variable called "foreach", anyway?) and edited usertype.dat in VC7.1 so its colored blue now.

Very happy.
Sample code:
std::string s = "hello, this is just a test";foreach(char& c, s){	c++;}
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
I found BOOST_FOREACH to be terribly leaky. It will fail with incomprehensible error messages in the weirdest situations.

I can't remember the specifics any longer, but the first (and last) real problem I had with it went something like this:
std::map<std::string, SomethingElse> mapOfStuff;foreach (std::pair<std::string, SomethingElse>& iter, mapOfStuff) // Fails, with an unintelligible error message{ ... }typedef std::pair<std::string, SomethingElse> PairOfThings;foreach (PairOfThings& iter, mapOfStuff) // works{ ... }


I'd rather like to see both typeof and auto introduced into the language. They can frequently be used for the same thing, but they don't always overlap.
"There is only one everything"
Quote:Original post by the Speed Bump
I found BOOST_FOREACH to be terribly leaky. It will fail with incomprehensible error messages in the weirdest situations.

I can't remember the specifics any longer, but the first (and last) real problem I had with it went something like this:
std::map<std::string, SomethingElse> mapOfStuff;foreach (std::pair<std::string, SomethingElse>& iter, mapOfStuff) // Fails, with an unintelligible error message

It's not "leaky." The problem you posted is not the fault of BOOST_FOREACH, it's just because of the C++ preprocessor. Remember, BOOST_FOREACH is a macro -- there is a comma in "std::pair<std::string, SomethingElse>& iter." That comma is interpretted as an argument separator since it is not inside of matching parenthesis in the argument. That's something you always have to watch out for when working with all macros in C++, unfortunately. So what you actually did was pass an extra argument to your macro (with the first two being the broken up version of your intended first argument).

I remember hearing talks about the new standard possibly allowing matching < and > in templates to act the same way as matching parenthesis when passing them to macros, though I personally do not advocate that since it implies either the preprocessor would have to recognize templates, which means it would have to do more complex parsing, otherwise it would also improperly recognize commas between logical greater than and less than operators in separate arguments as not being argument separators, which would only successfully fix one problem by introducing a new one. Both of those solutions would also potentially break older code.
I'd like to point you to matt wilson's book 'imperfect c++' here. In it he describes the concept of 'ranges' (there's also a range implementation in boost, for those who can't live without it).

see the sample chapter 34 on the book's website at [link]http://synesis.com.au/publishing/imperfect/cpp/impcpp_chapter_34.pdf[/link].
matt is using ranges to create a c++ foreach style that i really like.

what do you think ?

This topic is closed to new replies.

Advertisement