Implement Foreach in C ++, the Poor Man Approach

There are happy people working with boost and Qt. In my current “embedded” project, I have to use container classes for home use. Ok, enough to complain.

I tried to implement a simple and standalone foreach:

#define ForEachString(S,C) TString S;\ for ( int i=0; i<C.GetSize() && (!!(&(S=C[i]))); ++i ) 

Iterates through a string list that has the op [] and GetSize () methods. For example:.

 TStringList tables; ForEachString( table, tables ) { //do sth. with tab. } 

Because of the ugly thing, each type of container requires its own macro. So my question is: is it possible to make the container independent and still autonomous (all the macro definition needed inside )?

Regards, Valentin

+7
c ++
source share
6 answers

Perhaps you can parameterize type T:

 #define ForEach(T,S,C) TS;\ for ( int i=0; i<C.GetSize() && (!!(&(S=C[i]))); ++i ) TStringList tables; ForEach( TString, table, tables ) { //do sth. with tab. } 
+6
source share

I would recommend this

 #define ForEachString(S,C) \ if(bool _j_ = false) ; else for (int _i_ = 0; _i_ < C.GetSize() && !_j_; ++_i_, _j_ = !_j_) for(S = C[_i_]; !_j_; _j_ = true) TStringList tables; ForEachString(TString table, tables) { //do sth. with table } 

Minor actions with _j_ necessary so as not to interrupt the break inside the loop. Best use names such as _i_ and _j_ , so as not to interfere with user local loop variables.

+4
source share

Your macro is dangerous. Consider:

 if (<condition>) ForEachString(table, tables) { // do something } 

In addition, S is placed in the coverage area. Thus, you cannot have two ForEachString calls in the same block.

If you have a short-term compiler, for-loops ranges are part of C ++ 0x

Again, with C ++ 0x, you can replace TString S; on decltype(C[0]) S;

Or just enter the macro type:

 #define ForEachString(T, S, C) TS; ... 
+2
source share

Boost libraries have an implementation of a macro of the foreach type called BOOST_FOREACH, which does just that. It is container independent and can also work with raw C-style arrays and strings. Implementation is nothing more than fear (lots of crazy template mechanisms for type introspection), but the net result is fast, meager, average and widely used. You can find more information about this here .

Hope this helps!

+2
source share
 #define MY_CONTAINER(a, b) ab; \ typedef a::iterator b##_itr; #define for_each(itr, a) for(a##_itr itr = a.begin(); itr != a.end(); ++itr) MY_CONTAINER(vector<int>, vnVec); vnVec.push_back(2); vnVec.push_back(3); vnVec.push_back(10); for_each(itr, vnVec) cout << *itr << endl; 
0
source share

If your goal in creating this macro is to learn, I recommend that you read Eric Niebler's explanation of how to implement foreach, as Johannes Schaub - litb points to ( this ). He tells in detail about all the traps that he encounters when trying to solve this problem.

If your main task is simply to get a working foreach macro, the function is documented and passed on to Boost by Eric Nibler as BOOST_FOREACH .

The wiki community, as I am simply repeating what Johannes said.

-one
source share

All Articles