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.
精彩评论