※ 引述《descent (“雄辩是银,沉默是金”)》之铭言:
: 最近看了 sicp 5.2 的 recusive + callback 的 scheme 写法,
: 弄懂之后写了个 c++ 的版本。
: 有兴趣的朋友参考看看。
: 想顺便问问看, std::function 可以省下来吗? 我直接传递
: std::function 那个 lambda function, compile 不会过。
推 kwpn: 编译过不了的问题,应该先简化程式码来查问题出在哪. 01/19 19:59
我觉得一般而言应该可以省下来才对(template type deduction 不会有问题),
但这里又递回, 我怀疑是造成编译不过的原因, 因为每次都会有个新的 type 出来,
又递回呼叫自己(一个 template function), 造成 instantiate 出一个新的函式,
结果新的函式中 lambda 的 type 又不一样了.
一个演示这个现象的例子(编译不过):
template<typename F>
void loop(F f) {
loop([](){});
}
这里无论是把传进来的参数手动标 type 或是把新的 lambda function 手动标 type
(例如 loop<function<void()>>([](){}); )都可以解决.
题外话是, polymorphic recursion type inference 是 undecidable.
(这里的 polymorphic 是参数式多型)
: 一个 lambda function 的 type 应该怎么描述? 为什么需要把 type 写出来, c++ 可不
: 是 scheme , 都不用宣告的, 所以不知道怎么写 lambda function 的type, 要怎么传
: lambda function 给 function 当参数呢? 我想到邪恶万用的 auto。
: 31 auto func = [] () { cout << "Hello world" << endl; }
因为 C++ 的作法中, lambda 的 type 是 compiler 唯一生成的, 每个都不一样,
没有标准的方法可以算出来(n4296 5.1.2.3). 这跟一般函数式语言不一样.
: 可以, 不过带有 capture-list 就不行了。
: 81 auto func = [&] () { cout << "Hello world" << endl; }
这边我其实不太懂@@ 这段程式里可以用 auto 存
我怀疑是其他因素造成编译不过
template<typename F>
int f(F g) {
return g() - 1;
}
int main(int argc, char **argv) {
auto x = [&]() { return argc; };
return f(x);
}
: 而且, 在 function 的 prototype 也不能写 auto 来传入 lambda function。
: void f1(auto F);
: fa(func);
: 这样是不行的。
所以才像 extract 一样用 template 来接 lambda. C++14 的 generic lambda
倒是可以放 auto...但也差不多只是 template 而已.
auto add = [](auto n, auto m) { return n + m; };
: 所以我想到是不是可以用 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 来传递。
话说 C++ 的 lambda 常常就是用 function object 来实作的...?
std::function 是多包了一层还顺便把接口统一了, 包含其他可呼叫的东西
: 最后修改函式的宣告, 使用 template 来宣告一个 template function, 这样就可以接受
: std::function 转过的 function。
已经用 std::function 转过的话, 可能不是很需要用 template 来接, 直接用
std::function 就好了, 就是
void extract(
const string &str,
std::function<void(const string&, const string&)> receive)
{
}
: 不过这样有什么好处吗? 辛苦理解了这些新东西, 但他们能带来更好的效益吗? 花时间学
: 习划算吗? 看看 scheme 和 c++ 的版本, c++ 写来辛苦不少。c++11 加入了不少东西,
: 还有 c++14, 这些都是负担很大的学习, 我的建议是: 取你想用的来学习, 不必有想把
: c++ 全摸透的想法, 对于 template 我就很头疼, 几乎看不懂比较复杂的 template 程式
: 码, 我愿意学习难度高的 c++ 是因为她的弹性和效率, 可不是拿来折磨自己用的, 一旦
: 没有了效率优势, 我可能得找候补人选。
: 对于 std::function 的行为, 我实在好奇, 这是怎么完成的呢? c++ 越来越神奇了。
猜测应该就只是把传进来的 function object/function pointer/whatever 存起来,
主要的问题是 type 的部份...