开发者

Foreach implementation in C++, a Poor man's approach

There are happy people working with boost and Qt. In my current "embedded" project I have to use home-made container classes. OK, enough complain开发者_运维技巧ing.

I've tried to implement an easy and self-contained foreach like that:

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

It iterates through a string-list which has op[] and GetSize() methods. E.g.:

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

Of cause, the ugly thing is, each container type requires its own macro. Therefore my question: Is it possible to do it container independant and still self contained (all required stuff within the macro definition)?

Regards, Valentin


Perhaps you could parameterise on the type T:

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

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


I would recommend this one

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

The weird actions with _j_ are needed to not break break inside the loop. Best use names like _i_ and _j_ so to not interfere with user's local loop variables.


Your macro is dangerous. Consider:

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

Also, S is put into the enclosing scope. So you can't have two ForEachString calls in the same block.

If you have a bleeding-edge compiler, range-based for-loops are part of C++0x

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

Or, just make the type part of the macro:

#define ForEachString(T, S, C) T S; ...  


The Boost libraries have an implementation of a foreach-like macro called BOOST_FOREACH which does just this. It's container-independent and can also work on raw arrays and C-style strings. The implementation is nothing short of terrifying (lots of crazy template machinery for type introspection), but the net result is fast, lean, mean, and widely-used. You can find more information about this here.

Hope this helps!


#define MY_CONTAINER(a, b) a b; \
    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;


If your goal in creating this macro is to learn, I recommend you read Eric Niebler's explanation of how to implement foreach, pointed to by Johannes Schaub - litb (this). It goes into detail about all the pitfalls one encounters when trying to solve this problem.

If your main concern is to just get a working foreach Macro, the function is documented and submitted to Boost by Eric Niebler as BOOST_FOREACH .

Community wiki, since I'm just repeating what Johannes said.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜