你应该有一个概念没有搞懂:
C++ 的 lambda 其实是个 functor
在你写 lambda 的当下有一个 class 在此成立, 并产生一个实体
lambda 函式内容则是此 class 的 operator () 内容
这个 operator () 默认是有常数性, 也就是在函式中这 lambda class 是当做常数
(其实跟平常 class 宣告里在 member function 宣告后面加上 const 的意思一模一样
之所以这么设定的理由可见这连结 http://stackoverflow.com/questions/5501959/ )
所有被 capture by value 的变量都是这个 class 的成员变量
在 lambda 产生的当下产生实体时会复制进去
※ 引述《dreamboat66 (小嫩)》之铭言:
: 写程式遇到一个compile error原本看不出来原因
: 简化一下问题如下
: http://ideone.com/9Vqbvu
: 如果真的遇到这种case
: 我要很大方的冠上mutable吗?
: 还是想办法里面const cast拿掉const让move成功
所以在这里, 里面的 f2 和外面的 f2 是不同的变量
@@@+ 和 @@@- 之间的那次复制就是复制出里面的 f2 的那次
因此两个 f2 既然没关系, 使用 move 也就没有意义了
move 没有用的原因确实是常数性没错
但这是因为这个 operator () 的常数性, 使得其成员物件全部都是 const
这里如果你要把外面的 f2 给 move 进来的话
可以使用下面的 C++14 的带初始化 capture, 写 [f2 = move(f2)](...){...}
这样在建构时就会把外面的 f2 给 move 进去
: 如果惯上mutable的话
: http://ideone.com/s5KtOq
: 又遇到奇怪问题
: 为什么他要保留const 这属性, 如果alias他名字(这好像c++14才能这样写?)就不会...
: 这有什么特殊含意吗? 因为用template 推型别的观念 const是不会保留的呀
: 以上
: 谢谢
所以这里也不是 alias
而是这个 lambda class 里的两个成员变量 f2 和 f3, 都由外面的 f2 复制而来
这个 f3(f2) 是当做有个 auto f3(f2); 卡在这 lambda 宣告之前
但不在外面的 scope 里
所以后一个指向 f3(f2) 的 error 就是因为这个 f2 是外面的 f2, 那是 const
但你却宣告了 (lvalue-)copy ctor 为 explicit
不过这个先不管, 你的问题是在 Bar(f3) 和 Bar(f2) 的差别
f3 跟 f2 的差别在于 f2 继承自它抓取的变量的常数性, 但 f3 却是一个全新的变量
下面这个连结应该回答了你这部份的问题
http://stackoverflow.com/questions/31485041/
解法里面也提到了, 既然你有 C++14 的带初始化 capture
写 [f2 = f2] 就好, 这样如上所言这里就会用上 auto 的规则, 常数性就不见了
或是你还想要把外面的 f2 给 move 进来那就一样 [f2 = move(f2)]