这个FOREACH使用了GCC的扩展特性typeof和({}),所以只保证能在linux下玩哦。
源程序 foreach.h
#ifndef _MACRO_FOREACH_H_
#define _MACRO_FOREACH_H_
#define FOREACH_USE_ITERATOR(each_var, it_begin, it_end) \
if(int is_break_used_for_foreach=0){}else\
for(typeof(it_begin) it = it_begin, iend = it_end; \
(!is_break_used_for_foreach && (it!=iend)); ++it)\
for(typeof(*it) each_var = *it; 1; __extension__({break;}))
#define FOREACH_USE_STL_CONTAINER(each_var, container) \
FOREACH_USE_ITERATOR(each_var, container.begin(), container.end())
#define BREAK ({is_break_used_for_foreach = 1; break;})
#define CONTINUE ({continue;})
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
#define ARRAY_BEGIN(array) (array+0)
#define ARRAY_END(array) (array+ARRAY_SIZE(array))
#define EACH_ARRAY(each_var, array)\
FOREACH_USE_ITERATOR(each_var, ARRAY_BEGIN(array), ARRAY_BEGIN(array))
#define FOREACH FOREACH_USE_STL_CONTAINER
#define foreach FOREACH
#define EACH_RANGE(var, it_begin, it_end)\
for(typeof(it_begin) it = it_begin, iend = it_end; (it!=iend); ++it)\
for(typeof(*it) each_var = *it; 1; __extension__({break;}))
#define EACH(var, container) EACH_RANGE(var, container.begin(), container.end())
#define FOR_RANGE(var, start, end)\
for(typeof(start) var = start, iend = end; var != end; ++var)
#define FOR(var, container) FOR_RANGE(var, container.begin(), contianer.end())
#define MAP_USE_ITERATOR(begin, end, result, var, func)\
FOREACH_USE_ITERATOR(var, begin, end){ \
result.push_back((func));\
}
#define MAP_USE_STL_CONTAINER(container, result, var, func) MAP_USE_ITERATOR(container.begin(), container.end(), result, var, func)
#define MAP MAP_USE_STL_CONTAINER
#define FILTER_USE_ITERATOR(begin, end, result, var, func)\
FOREACH_USE_ITERATOR(var, begin, end){ \
if((func)) \
result.push_back(*cur);\
};
#define FILTER_USE_STL_CONTAINER(container, result, var, func) FILTER_USE_ITERATOR(container.begin(), container.end(), result, var, func)
#define FILTER FILTER_USE_STL_CONTAINER
#endif //_MACRO_FOREACH_H_
测试代码 foreach.test.cpp
#include <map>
#include "foreach.h"using namespace std;
void test1(int);
void test2(int);map<int, int> c;
int main(int argc, char **argv) {
if(argc<4) {
printf("too less param, input 3 params!\n");
return 0;
}int sel = atoi(argv[1]);
void (*test)(int) = NULL;
switch(sel) {
case 1:
test = test1;
break;
case 2:
test = test2;
break;
}int num = atoi(argv[2]);
for(int i =0; i<num; ++i) {
c[i]=i;
}int len = atoi(argv[3]);
for(int i =0; i<len; ++i) {
test(num);
}
}void test1(int num){
int s = 0;
foreach(const & a, c)
{
s+=(a.first+a.second);}
}void test2(int num){
int s = 0;
map<int, int>::iterator it = c.begin(), iend = c.end();
for(;it!=iend; ++it)
{
pair<int, int> const &a = *it;
s+=(it->first + it->second);
}
}
编译
g++ -O2 ./foreach.test.cpp -o foreach测试
foreach宏: time ./foreach 1 10000 50000
real 0m5.288s
user 0m5.241s
sys 0m0.015s
标准for循环: time ./foreach 2 10000 50000
real 0m5.600s
user 0m5.533s
sys 0m0.031s
测试结果很让人吃惊,竟然宏版本还更快。 有时间要用 IDA看一下反汇编代码了。
早期实现
一开始不知道gcc 的 __extension__ 关键字,FOREACH_USE_ITERATOR实现的方式如下:
#define FOREACH_USE_ITERATOR(each_var, it_begin, it_end) \
typeof(it_begin) FOREACH_VAR(it) = it_begin;\
typeof(it_end) FOREACH_VAR(iend) = it_end; \
if(likely(FOREACH_VAR(it)!=FOREACH_VAR(iend))){ \
goto FOREACH_LABLE( into ); \
}else {\
goto FOREACH_LABLE( exit );\
}\
FOREACH_LABLE( exit ) :\
if(0)\
FOREACH_LABLE( into ) :\
for(typeof(*FOREACH_VAR(it)) each_var = *FOREACH_VAR(it);\
1;\
({\
++FOREACH_VAR(it);\
if(likely(FOREACH_VAR(it) != FOREACH_VAR(iend))){ \
goto FOREACH_LABLE( into );\
}else {\
goto FOREACH_LABLE( exit );\
}; 1;\
})\
)