[分享] c++11 lambda & std::function

楼主: descent (“雄辩是银,沉默是金”)   2015-01-19 19:13:42
最近看了 sicp 5.2 的 recusive + callback 的 scheme 写法,
弄懂之后写了个 c++ 的版本。
有兴趣的朋友参考看看。
想顺便问问看, std::function 可以省下来吗? 我直接传递
std::function 那个 lambda function, compile 不会过。
t.cpp
1 // ref:http://goo.gl/k5MgDG (
http://kheresy.wordpress.com/2010/05/27/c0x%a1Glambda-expression/ )
2 #include <vector>
3 #include <algorithm>
4 #include <iostream>
5 #include <string>
6 #include <typeinfo>
7 #include<functional>
8
9 using namespace std;
10
84 template<typename Func>
85 void extract(const string &str, Func receive)
86 {
87 if (str.length() == 0)
88 {
89 string e1, e2;
90 receive(e1, e2);
91 }
92 else
93 {
94 // ref:http://goo.gl/hgh1EI (
http://www.cnblogs.com/ttss/p/4100917.html )
95 // std::function<int(int ,int)>func=add;
96 // <int(int,int)>是例化模板,表示返回值int,函2,(int,int),
97 // 即int(*pfunc)(int ,int )型的函
98 std::function<void(const string&, const string&)> f1 = [&](const
string &n, const string &s)
99 {
100 char next_ch = str[0];
101 string tmp_str;
102
103 tmp_str.push_back(next_ch);
104
105 #ifdef MORE_INFO
106 cout << "n: " << n << endl;
107 cout << "s: " << s << endl;
108 cout << "next_ch: " << next_ch << endl;
109 #endif
110
111 if ('0' <= next_ch && next_ch <= '9')
112 {
113 string new_str = n + tmp_str;
114 #ifdef MORE_INFO
115 cout << "new_str: " << new_str << endl;
116 cout << "===========" << endl;
117 #endif
118 receive(new_str, s);
119 }
120 else
121 {
122 string new_str = s + tmp_str;
123 #ifdef MORE_INFO
124 cout << "new_str: " << new_str << endl;
125 cout << "===========" << endl;
126 #endif
127 receive(n, new_str);
128 }
129 };
130
131 extract(str.substr(1), f1);
132 }
133 }
134
135 void assemble(string &str)
136 {
137 extract(str,
138 [] (const string &n, const string &s)
139 {
140 cout << n << endl;
141 cout << s << endl;
142 }
143 );
144 }
145
146 int main(int argc, char *argv[])
147 {
154 string str="x51ca2yz";
155 cout << str << endl;
157 assemble(str);
158 return 0;
159 }
一个 lambda function 的 type 应该怎么描述? 为什么需要把 type 写出来, c++ 可不
是 scheme , 都不用宣告的, 所以不知道怎么写 lambda function 的type, 要怎么传
lambda function 给 function 当参数呢? 我想到邪恶万用的 auto。
31 auto func = [] () { cout << "Hello world" << endl; }
可以, 不过带有 capture-list 就不行了。
81 auto func = [&] () { cout << "Hello world" << endl; }
而且, 在 function 的 prototype 也不能写 auto 来传入 lambda function。
void f1(auto F);
fa(func);
这样是不行的。
所以我想到是不是可以用 function pointer 的方式传进去, L31 的那种型式可以, ex:
void f1(void (*F)());
fa(func);
这样就可以了, 但我想传入 L81 那种型式的 lambda function 该怎么办呢? 为什么有
capture-list 不能以 function pointer 传入呢? 因为他需要把外面那层的变量存起来
, 这不是 c++ function 应该有的样子, 那 c++ 有什么机制可以把东西存起来, 而且也
有像 funciton 的行为呢? 你一定马上想到 function object, 这就是
recursive_call_back.cpp 为什么要用上 function object 的原因。
有着 capture-list 的 lambda function 有个很酷的名称 - lexical closure, 中国翻
译成“闭包”, 台湾我不知道翻译成什么? 这东西感觉起来是不是和 function object
很像, lexical closure 搞不懂, 用 function object 来联想也许就容易懂了。
但是我不想传 function object, 那个我已经做过了, 那这个东西的 type 要怎么写呢?
c++11 标准程式库知道这很让我们伤脑筋, 提供了 std::function 来完成这样的事情。
所以我出动了 std::function 来将 BB 转成 function object, 就可以当作 lambda
function 的 type 来传递。
最后修改函式的宣告, 使用 template 来宣告一个 template function, 这样就可以接受
std::function 转过的 function。
不过这样有什么好处吗? 辛苦理解了这些新东西, 但他们能带来更好的效益吗? 花时间学
习划算吗? 看看 scheme 和 c++ 的版本, c++ 写来辛苦不少。c++11 加入了不少东西,
还有 c++14, 这些都是负担很大的学习, 我的建议是: 取你想用的来学习, 不必有想把
c++ 全摸透的想法, 对于 template 我就很头疼, 几乎看不懂比较复杂的 template 程式
码, 我愿意学习难度高的 c++ 是因为她的弹性和效率, 可不是拿来折磨自己用的, 一旦
没有了效率优势, 我可能得找候补人选。
对于 std::function 的行为, 我实在好奇, 这是怎么完成的呢? c++ 越来越神奇了。
我虽然搞懂了, 但是要我以这种思维来写程式, 呃 ... 我功力还不够。自从学了 c++11
后, 连自己都看不懂自己在写什么了。
scheme 和 recursive_call_back.cpp 的版本可以参考:
http://descent-incoming.blogspot.tw/2015/01/recursive-callback-function.html
( http://goo.gl/gClt7L )
// 本文使用 Blog2BBS 自动将Blog文章转成缩址的BBS纯文字 http://goo.gl/TZ4E17 //
blog 版本, 呃 ... 这次没有 blog 版本 XD
作者: kwpn (ITSST)   2015-01-19 19:59:00
编译过不了的问题,应该先简化程式码来查问题出在哪.
作者: PkmX (阿猫)   2015-01-20 00:14:00
其实简化来看这个extract就只是某种fold的变体...要写这么functional的程式还是来写欢乐的haskell吧XD"直接转换的版本:http://ideone.com/8sFb9Massemble'是用foldl' + lens的一行版
作者: suhorng ( )   2015-01-20 01:33:00
(!) PkmX 出现了XD普通 cont.-passing style 竟然有这种 lens 写法XD
作者: PkmX (阿猫)   2015-01-20 16:01:00
喔对没错这个是CPS 昨天一直突然想不起来这个叫啥XDrz...

Links booklink

Contact Us: admin [ a t ] ucptt.com