Reading the answer from Capturing a reference by reference in a C++11 lambda makes me think that the following code generates undefined behavior because of the ended lifetime of i
in the lambda-capture. Is that right for C++1y? I am asking because g++ 4.8.2
translates the code just fine.
#include <iostream>
auto captureFct( ) {
int i=0;
auto set = [&i](int _i){ i=_i; };
auto get = [&i](){ return i; };
return std::pair<decltype(set),decltype(get)>(set,get);
}
int main() {
auto myPair = captureFct();
auto set1 = myPair.first;
auto get1 = myPair.second;
auto myPair1 = captureFct();
auto set2 = myPair1.first;
auto get2 = myPair1.second;
std::cout << "\nget1:" << get1() << " get2:" << get2() << '\n';
set1(1); set2(2);
std::cout << "\nget1:" << get1() << " get2:" << get2();
}
/*
Local Variables:
compile-command: "g++ -std=c++1y lambda.cc -o a.exe && ./a.exe"
End:
*/
The output is interesting:
get1:0 get2:0
get1:2 get2:2
It seems that the same reference is used for all lambdas.
This behavior differs from the behavior of the following elisp code (as close to the c++ code as possible):
(defun captureFct ()
(lexical-let ((i 0))
(list :set (lambda (_i) (setq i _i))
:get (lambda () i))))
(setq myPair (captureFct))
(setq myPair1 (captureFct))
(message "\nget1: %d get2: %d"
(funcall (plist-get myPair :get))
(funcall (plist-get myPair1 :get)))
(funcall (plist-get myPair :set) 1)
(funcall (plist-get myPair1 :set) 2)
(message "\nget1: %d get2: %d"
(funcall (plist-get myPair :get))
(funcall (plist-get myPair1 :get)))
The output of the elisp code is:
get1: 0 get2: 0
get1: 1 get2: 2
I think I know already the answer. But, I post this question anyway since it is interesting for folks that do both elisp and c++.
Last but not least a C++ version that works like the elisp version:
#include <iostream>
#include <memory>
auto captureFct( ) {
std::shared_ptr<int> pi(new int(0));
auto set = [pi](int _i){ *pi=_i; };
auto get = [pi](){ return *pi; };
return std::pair<decltype(set),decltype(get)>(set,get);
}
int main() {
auto myPair = captureFct();
auto set1 = myPair.first;
auto get1 = myPair.second;
auto myPair1 = captureFct();
auto set2 = myPair1.first;
auto get2 = myPair1.second;
std::cout << "\nget1:" << get1() << " get2:" << get2() << '\n';
set1(1); set2(2);
std::cout << "\nget1:" << get1() << " get2:" << get2();
}
/*
Local Variables:
compile-command: "g++ -std=c++1y lambda.cc -o a.exe && ./a.exe"
End:
*/