Sign in to follow this  
Storyyeller

best c++ foreach macro?

Recommended Posts

Storyyeller    215
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
Zlodo    654
[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
Brother Bob    10344
[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
ChaosEngine    5185
[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
Brother Bob    10344
[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
Storyyeller    215
[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
Zlodo    654
[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
rip-off    10976
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
gekko    478
[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
fastcall22    10840
[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
taz0010    277
[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
_the_phantom_    11250
[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
alvaro    21246
[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
Nitage    1107
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
Brother Bob    10344
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
fastcall22    10840
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

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