Sign in to follow this  

best c++ foreach macro?

This topic is 2334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Note: Assume hypothetically that boost foreach doesn't exist.
What is the best way to write a C++ foreach macro?

The most obvious method is something like
[source='cpp'] #define foreach(var, container) for(auto var = (container).begin(); var != (container).end(); ++var)
foreach(foo, foos) { (*foo) *= 3; } [/source]

However, this forces you to dereference the pointer/iterator. It's usually more convenient to have a reference. One possibility I thought of is
[source='cpp'] #define foreach(var, container) for(auto iter = (container).begin(); iter != (container).end(); ++iter) {auto& var = *iter;
foreach(foo, foos) foo *= 3; } [/source]

The main problem with this is that the missing { completely mangles IDE code folding.

Share this post


Link to post
Share on other sites
[quote name='fastcall22' timestamp='1311226132' post='4838316']
Use of "auto"? Use lambdas:
[/quote]

If you have a compiler whose support of C++11 is far along enough to support auto and lambdas, chances are that it supports C++11's foreach syntax anyway:

[code]
for( auto& val : container )
{
}
[/code]

gcc 4.6 supports this, I'm not sure about visual studio 2010. It was just added in clang too iirc.

Share this post


Link to post
Share on other sites
[quote name='Zlodo' timestamp='1311237640' post='4838351']
gcc 4.6 supports this, I'm not sure about visual studio 2010. It was just added in clang too iirc.
[/quote]
VS10 does support a [i]for each[/i] construct, but not the standard one.
[source]
for each(auto &val in container)
{
}
[/source]

Share this post


Link to post
Share on other sites
[quote name='Brother Bob' timestamp='1311240100' post='4838361']
[quote name='Zlodo' timestamp='1311237640' post='4838351']
gcc 4.6 supports this, I'm not sure about visual studio 2010. It was just added in clang too iirc.
[/quote]
VS10 does support a [i]for each[/i] construct, but not the standard one.
[source]
for each(auto &val in container)
{
}
[/source]
[/quote]

I thought that was the C++/CLI syntax. Does it work with native C++ code?

Share this post


Link to post
Share on other sites
[quote name='ChaosEngine' timestamp='1311245933' post='4838384']
[quote name='Brother Bob' timestamp='1311240100' post='4838361']
[quote name='Zlodo' timestamp='1311237640' post='4838351']
gcc 4.6 supports this, I'm not sure about visual studio 2010. It was just added in clang too iirc.
[/quote]
VS10 does support a [i]for each[/i] construct, but not the standard one.
[source]
for each(auto &val in container)
{
}
[/source]
[/quote]

I thought that was the C++/CLI syntax. Does it work with native C++ code?
[/quote]
Yes, it does. I don't know the details or limitations with it, or how it compares to the standard syntax, but it does work for iterating over all values in a container supporting the begin/end semantics at least.

Share this post


Link to post
Share on other sites
[quote name='Zlodo' timestamp='1311237640' post='4838351']
[quote name='fastcall22' timestamp='1311226132' post='4838316']
Use of "auto"? Use lambdas:
[/quote]

If you have a compiler whose support of C++11 is far along enough to support auto and lambdas, chances are that it supports C++11's foreach syntax anyway:
[/quote]

Not necessarily. GCC supported auto as early as 4.4, but didn't support ranged based for until 4.6

Share this post


Link to post
Share on other sites
[quote name='Storyyeller' timestamp='1311253113' post='4838419']Not necessarily. GCC supported auto as early as 4.4, but didn't support ranged based for until 4.6
[/quote]
Which is why I said "auto AND lambdas", my reasoning being that lambdas are more complex to implement than the for each construct and thus it is likely that by the time they get around to implement it they already did the foreach construct (which is the case with clang, for instance).

Share this post


Link to post
Share on other sites
Well, the keywords still work if you wrote an inner loop inside the lambda, but I guess this isn't what you are asking. Lambdas have nothing to do with loops, even though they make it convenient to work with many Standard C++ algorithms, which are often thought of as loops.

An early return would be like "continue". Break would be harder to simulate, but picking a different algorithm might help (e.g. std::find_if).

Share this post


Link to post
Share on other sites
[quote name='Zlodo' timestamp='1311237640' post='4838351']
If you have a compiler whose support of C++11 is far along enough to support auto and lambdas, chances are that it supports C++11's foreach syntax anyway:

[code]
for( auto& val : container )
{
}
[/code]

gcc 4.6 supports this, I'm not sure about visual studio 2010. It was just added in clang too iirc.
[/quote]

Visual Studio 2010 does not support this feature, and it supports auto and lambdas.

Share this post


Link to post
Share on other sites
[quote name='gekko' timestamp='1311316067' post='4838798']
Visual Studio 2010 does not support this feature
[/quote]

[url=http://blogs.msdn.com/b/arich/archive/2004/09/08/227139.aspx]What?[/url] [url=http://www.gamedev.net/topic/606774-best-c-foreach-macro/page__view__findpost__p__4838361]:|[/url]

Share this post


Link to post
Share on other sites
[quote name='fastcall22' timestamp='1311316380' post='4838799']
[quote name='gekko' timestamp='1311316067' post='4838798']
Visual Studio 2010 does not support this feature
[/quote]

[url="http://blogs.msdn.com/b/arich/archive/2004/09/08/227139.aspx"]What?[/url] [url="http://www.gamedev.net/topic/606774-best-c-foreach-macro/page__view__findpost__p__4838361"]:|[/url]
[/quote]

The syntax is nonstandard. I don't know why they never bothered to implement foreach the proper way.

Share this post


Link to post
Share on other sites
[quote name='taz0010' timestamp='1311323671' post='4838811']
The syntax is nonstandard. I don't know why they never bothered to implement foreach the proper way.
[/quote]

Probably down to feature lock down and the state of the spec at the time; effectively they have the underlaying code to do it properly just didn't have the time/man power to push onto it, probably in favour of some other more commonly used feature.

Share this post


Link to post
Share on other sites
[quote name='Zlodo' timestamp='1311254964' post='4838433']
[quote name='Storyyeller' timestamp='1311253113' post='4838419']Not necessarily. GCC supported auto as early as 4.4, but didn't support ranged based for until 4.6
[/quote]
Which is why I said "auto AND lambdas", my reasoning being that lambdas are more complex to implement than the for each construct and thus it is likely that by the time they get around to implement it they already did the foreach construct (which is the case with clang, for instance).
[/quote]

(Hmmm... I meant to reply to this, not give it my approval. How come I can't change my mind after I have rated a comment?)

That is pretty strange logic, and it doesn't work. gcc 4.5.2 has both auto and lambdas, but does not support range for.

Share this post


Link to post
Share on other sites
So...

[code]
#if ... Visual Studio
# define for_each for each
#else
# define for_each for
# define in :
#endif

for_each(auto& val in container) {
...
}[/code]

I feel dirty even writing that.



Share this post


Link to post
Share on other sites
If you should make a macro for it, don't make it on such a fine level that you have to macro-define the individual keywords making it up; make it a single macro for the whole construct, not macros for individual keywords. Making a macro for such an ambiguous word "in" to translate to something else, on a token basis outside the language, is likely to bite you back big times sooner or later.

At the very least, make it a two-parameter macro; one for the loop variable and one for the container, and construct the loop with proper syntax within the macro instead.

Share this post


Link to post
Share on other sites
Hidden
[quote name='Nitage' timestamp='1311361168' post='4839070']
[code]
#if ... Visual Studio
# define for_each for each
#else
# define for_each for
# define in :
#endif

for_each(auto& val in container) {
...
}[/code]

I feel dirty even writing that.
[/quote]

You should. You're stomping on "std::for_each" >:(

Slightly better, but still dirty:
[code]
#if !defined(_MSC_VER)
#define each /* */
#define in :
#endif
[/code]

Share this post


Link to post

This topic is 2334 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this