python,c#,java里面都有类似于foreach的结构,stl里面虽然有for_each这个函数,但是感觉使用还是太繁琐了一些,所以就自己实现了一个。 先来看看stl里面的for_each函数,官方文档上的原型如下:
| Function for_each (InputIterator first, InputIterator last, Function f); |
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using
namespace
std;
void
myfunction
(int
i)
{
cout
<<
" "
<<
i;
}
struct
myclass
{
void
operator()
(int
i)
{cout
<<
" "
<<
i;}
}
myobject;
int
main
()
{
vector<int>
myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout
<<
"myvector contains:";
for_each
(myvector.begin(),
myvector.end(),
myfunction);
//
or:
cout
<<
"\nmyvector contains:";
for_each
(myvector.begin(),
myvector.end(),
myobject);
cout
<<
endl;
return
0;
}
|
不只函数原型有点不习惯,而且还要再写一个函数,比起python的实现方式,的确有点繁琐了:
我们来自己实现一个,方法肯定是用宏啦,我们来看一下第一个版本:
|
#define foreach(container,it,type) \
for(type::iterator
it
=
(container).begin();it!=(container).end();++it)
|
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <iostream> #include <string> #include <vector> #include <set> #include <map> using namespace std; #define foreach(container,it,type) \ for(type::iterator it = (container).begin();it!=(container).end();++it) int main(int argc, const char *argv[]) { set<string> s; s.insert("w"); s.insert("a"); s.insert("n"); foreach(s,it,set<string>) { cout<<*it<<endl; } /*map<unsigned,string> m; m[0]="x"; m[1]="w"; foreach(m,it,map<unsigned,string>) { cout<<it->first<<","<<it->second<<endl; }*/ return 0; } |
如果把注释掉的代码打开的话,就会报错,应该是宏无法处理逗号的原因。
而且调用起来还是有点繁琐对吧,python里面并没有要求传入容器类型,我们是不是也能把set这个参数省掉呢?
先来看一下这段代码:
|
typeof(10)
a;
a
=
100;
cout<<a<<endl;
|
这段代码是可以执行的,运行结果是100。从这一点出发,我们是不是能通过typeof(container)获得容器类型,然后通过typeof(container)::iterator创建遍历指针呢,我们来看第二个版本
| #define foreach(container,it) \ for(typeof(container)::iterator it = (container).begin();it!=(container).end();++it) |
然而很不幸,这段代码是无法运行的,编译结果如下:
|
test4.cpp|21|
error:
expected
initializer
before
"it"
test4.cpp|21|
error:
`it'
was not declared in this scope
test4.cpp|34| error: expected initializer before "it"
test4.cpp|34| error: `it'
was
not
declared
in
this
scope
|
有没有办法解决呢?
有的,我们用一个曲线救国的方法!typeof(container.begin()) ,哈哈!最终代码如下:
| #define foreach(container,it) \ for(typeof((container).begin()) it = (container).begin();it!=(container).end();++it) |
测试代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#include <vector>
#include <set>
#include <map>
using
namespace
std;
#define foreach(container,it) \
for(typeof((container).begin())
it
=
(container).begin();it!=(container).end();++it)
int
main(int
argc,
const
char
*argv[])
{
set<string>
s;
s.insert("w");
s.insert("a");
s.insert("n");
foreach(s,it)
{
cout<<*it<<endl;
}
map<unsigned,string>
m;
m[0]="x";
m[1]="w";
foreach(m,it)
{
cout<<it->first<<","<<it->second<<endl;
}
return
0;
}
|
输入结果如下:
OK!一切正常!这应该是形式比较简单的版本啦,如果各位有什么更好的建议,欢迎留言交流~
ps:
当然,其实你连it这个参数都可以省掉,但是根据pythonic的原则(好吧,我知道自己是在写C++),要简单但不能让人迷惑,所以建议还是把it这个参数保留。
FROM: http://www.vimer.cn/2010/10/%E5%9C%A8c%E4%B8%AD%E5%AE%9E%E7%8E%B0foreach%E5%BE%AA%E7%8E%AF%EF%BC%8C%E6%AF%94for_each%E6%9B%B4%E7%AE%80%E6%B4%81%EF%BC%81.html