# best c++ foreach macro?

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

## 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 on other sites
Use of "auto"? Use lambdas:

 std::for_each( container.begin(), container.end(), [&] ( const container_type::value_type& val ) { } ); 

##### Share on other sites
Turns out to be pretty difficult

##### Share on other sites

Use of "auto"? Use lambdas:

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:

 for( auto& val : container ) { } 

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

##### Share on other sites

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

VS10 does support a for each construct, but not the standard one.
[source]
for each(auto &val in container)
{
}
[/source]

##### 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.

VS10 does support a for each 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 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.

VS10 does support a for each 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 on other sites

[quote name='fastcall22' timestamp='1311226132' post='4838316']
Use of "auto"? Use lambdas:

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 on other sites
Not necessarily. GCC supported auto as early as 4.4, but didn't support ranged based for until 4.6

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 on other sites
Also, is it possible to continue or break with lambdas?

##### 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 on other sites

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:

 for( auto& val : container ) { } 

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

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

##### Share on other sites

Visual Studio 2010 does not support this feature

What? :|

##### Share on other sites

[quote name='gekko' timestamp='1311316067' post='4838798']
Visual Studio 2010 does not support this feature

What? :|
[/quote]

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

##### Share on other sites

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

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 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

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 on other sites
So...

 #if ... Visual Studio # define for_each for each #else # define for_each for # define in : #endif for_each(auto& val in container) { ... }

I feel dirty even writing that.

##### 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 on other sites
Hidden

 #if ... Visual Studio # define for_each for each #else # define for_each for # define in : #endif for_each(auto& val in container) { ... }

I feel dirty even writing that.

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

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