ã2015å¹´12æ24æ¥è¨è¼ : C++11 ã©ã ãå¼ã®æ£å¼ãªã¾ã¨ãã¯ããã¡ãã®ãã¼ã¸ãC++11 ラムダ式 - cpprefjp C++日本語リファレンスããåç §ãã¦ãã ããã
ä»ã¾ã§ã¯ã©ã ãå¼ã®ãªãã¸ã§ã³ãä¸ãããã³ã«å·®åã ãæ¸ãã¦ãã®ã§
C++0xã«æ¡æãããã©ã ãå¼ã®è§£èª¬ãããããã¦æ¸ãã¾ãã
ãC++03ã¾ã§ã®åé¡ç¹ã
C++03ã§ã¯ãé¢æ°ããã®å ´ã§ä½æãããã¨ãããã¨ãã§ããªãã£ããã
é¢æ°ãåãåãSTLã¢ã«ã´ãªãºã ã使ç¨ããå ´åã以ä¸ã®ããã«ãã¢ã«ã´ãªãºã ã«æ¸¡ãç¨ã®é¢æ°ãä½æããªããã°ãªãã¾ããã§ããã
struct is_even { typedef bool result_type; bool operator()(int x) const { return x % 2 == 0; } }; vector<int> v; find_if(v.begin(), v.end(), is_even());
ãC++0xã§ã®è§£æ±ºçã
C++0x ã§ã¯ãã©ã ãå¼ã¨ãããå¿åé¢æ°ãªãã¸ã§ã¯ããçæããããã®å¼ãæä¾ããã¾ãã
å
ã»ã©ã®is_evené¢æ°ãªãã¸ã§ã¯ãã使ç¨ããä¾ã¯ã以ä¸ã®ããã«æ¸ãç´ããã¨ãã§ãã¾ãã
vector<int> v; find_if(v.begin(), v.end(), [](int x) -> bool { return x % 2 == 0; });
ãã®ä¾ã§ã¯ããã©ã¡ã¼ã¿ã§intãåãåããboolãè¿ãé¢æ°ãªãã¸ã§ã¯ãããã®å ´ã§ä½æãã¦ã¢ã«ã´ãªãºã ã«æ¸¡ãã¦ãã¾ãã
ãæ»ãå¤åã®æ¨è«ã
ã©ã ãå¼ã¯æ»ãå¤ã®åãçç¥ãããã¨ãã§ããããã以ä¸ã®ããã«æ¸ããã¨ãã§ãã¾ãã
[](int x) { return x % 2 == 0; }
æ»ãå¤ã®åãçç¥ããå ´åãæ»ãå¤ã®åã¯ãreturnæãdecltypeããåã¨ãªãããã
ä¸è¨ã®ã©ã ãå¼ã¯ã以ä¸ã®ã©ã ãå¼ã¨åãæå³ã«ãªãã¾ãã
[](int x) -> decltype(x % 2 == 0) { return x % 2 == 0; }
returnæãæ¸ããªãå ´åãæ»ãå¤ã®åã¯voidã«ãªãã¾ãã
vector<int> v; for_each(v.begin(), v.end(), [](int x) { cout << x << endl; });
ãå¤æ°ã®ãã£ããã£ã
ã©ã ãå¼ã«ã¯ãå¤æ°ã®ãã£ããã£ã¨ããæ©è½ãããã¾ãã
ããã使ç¨ããã¨ãæå®ããå¤æ°ãã©ã ãå¼å
ã§ä½¿ç¨ãããã¨ãã§ãã¾ãã
ãã¨ãã°ã以ä¸ã¯rateå¤æ°ãã©ã ãå¼ã§ä½¿ç¨ããä¾ã§ãã
vector<int> v; int rate = 2; transform(v.begin(), v.end(), v.begin(), [rate](int x) { return x * rate; });
ä¸è¨ã®ã©ã ãå¼ã§ã¯ãrateå¤æ°ãã©ã ãå¼å
ã§ä½¿ç¨ããããã«ã [ ] ã®ä¸ã«rateå¤æ°ã渡ãã¦ãã¾ãã
[ ] ã¯ãã©ã ãå°å
¥å(lambda-introducer)ã¨ããã¾ãã
ãã®å ´åãrateå¤æ°ã®ã³ãã¼ãã©ã ãå¼ã«æ¸¡ããã¾ãã
å¤æ°ãã³ãã¼ã§ã¯ãªãåç §ã§ãã£ããã£ããã«ã¯ãå¤æ°ã®å é ã«&ãä»ãã¾ãã
vector<int> v; int sum = 0; for_each(v.begin(), v.end(), [&sum](int x) { sum += x; });
ããã§ã¯ãå¤æ°ãã¨ã«ãã£ããã£æ¹æ³(ã³ãã¼ãåç
§)ãæå®ãã¦å¤æ°ããã£ããã£ãã¦ãã¾ãã
å¤æ°ã®ãã£ããã£ã«ã¯ãåå¥æå®ã®ä»ã«ãããã©ã«ãã®ãã£ããã£æ¹æ³ãæå®ãããã¨ãã§ãã¾ãã
vector<int> v; int rate = 2; transform(v.begin(), v.end(), v.begin(), [=](int x) { return x * rate; });
vector<int> v; int sum = 0; for_each(v.begin(), v.end(), [&](int x) { sum += x; });
ããã§ã¯ãããã©ã«ãã®ãã£ããã£æ¹æ³ãæå®ããããã«ã=ã¨&ãæå®ãã¦ãã¾ãã
=ã¯å¤æ°ãããã©ã«ãã§ã³ãã¼ãã£ããã£ãã¾ãã
&ã¯å¤æ°ãããã©ã«ãã§åç
§ãã£ããã£ãã¾ãã
ã¾ããããã©ã«ãæå®ã¨åå¥æå®ãçµã¿åããããã¨ãã§ãã¾ãã
ãã®å ´åãããã©ã«ããã£ããã£æ¹æ³ãå
é ã«æ¸ãããã®æ¬¡ã«åå¥ã«ãã£ããã£æ¹æ³ãæå®ãã¾ãã
vector<int> v; int rate = 2; int sum = 0; for_each(v.begin(), v.end(), [&, rate](int x) { sum += x * rate; });
ä¸è¨ã®ã©ã ãå¼ã§ã¯ãããã©ã«ãã§åç §ãã£ããã£ããrateå¤æ°ãã³ãã¼ãã£ããã£ãã¦ãã¾ãã
ãthisã®ãã£ããã£ã
ã¡ã³ãé¢æ°å
ã§ã¯ãthisããã£ããã£ãããã¨ã§ã©ã ãå¼å
ã§ã¡ã³ãå¤æ°ãã¡ã³ãé¢æ°ã使ç¨ãããã¨ãã§ãã¾ãã
class hoge { vector<int> vec_; void disp(int i) const { cout << i << endl; } public: void call() const { for_each(vec_.begin(), vec_.end(), [this](int i){ disp(i); }); } };
ä¸è¨ã®ã©ã ãå¼ã§ã¯ãthisããã£ããã£ãã¦ãvectorã®åè¦ç´ ãhogeã¯ã©ã¹ã®privateã¡ã³ãé¢æ°dispã«æ¸¡ãã¦å®è¡ãã¦ãã¾ãã
ã¡ã³ãé¢æ°å
ã®ã©ã ãå¼ã¯ããã®ã¯ã©ã¹ã® friend ã¨è¦ãªãããã®ã§ãprivateã¡ã³ãã使ç¨ãããã¨ãã§ããã®ã§ãã
ãã©ã ãå¼ã«ãã£ã¦çæãããå¿åé¢æ°ãªãã¸ã§ã¯ãã
ã©ã ãå¼ãæ¸ããã¨ã§ããã®å ´ã«å¿åé¢æ°ãªãã¸ã§ã¯ããçæããã¾ãã
ãã¨ãã°ã以ä¸ã®ã©ã ãå¼ã§ã¯
int rate = 2; [rate](int x) -> int { return x * rate; }
以ä¸ã®ãããªé¢æ°ãªãã¸ã§ã¯ããçæããã¾ãã
class F { int rate; public: F(int rate) : rate(rate) {} F(const F&) = default; F(F&& other) : rate(static_cast<int&&>(other.rate)) {} F& operator=(const F&) = delete; int operator()(int x) const { return x * rate; } };
ããã§ã¯ãrateå¤æ°ãã³ãã¼ãã£ããã£ãã¦ãããããã©ã ãå¼ã«ãã£ã¦çæãããå¿åé¢æ°ãªãã¸ã§ã¯ãã¯ãrateå¤æ°ãã¡ã³ãå¤æ°ã¨ãã¦æã¡ã¾ãã
ã©ã ãå¼ã«ãã£ã¦çæãããå¿åé¢æ°ãªãã¸ã§ã¯ãã¯ããã£ããã£ã«ãã£ã¦ãã®ã¹ã³ã¼ãã®ç°å¢ãæã¤ãããã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã¨å¼ã°ãã¾ãã
ã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã¯ã以ä¸ã®ãããªç¹å¾´ãããã¾ãã
- æé»ã«å®ç¾©ãããã³ãã¼ã³ã³ã¹ãã©ã¯ã¿ãæã¤
- publicãªã ã¼ãã³ã³ã¹ãã©ã¯ã¿ãæã¤
- ã³ãã¼ä»£å ¥æ¼ç®åã¯deleteå®ç¾©ããã
- é¢æ°å¼ã³åºãæ¼ç®åã¯constã¡ã³ãé¢æ°
- ã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã®ãµã¤ãºã¯æè¨ãããªã
ãã©ã ãå¼ã®mutable修飾ã
ã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã®é¢æ°å¼ã³åºãæ¼ç®åã¯constã¡ã³ãé¢æ°ã®ãããã³ãã¼ãã£ããã£ããå¤æ°ãæ¸ãæãããã¨ã¯ã§ãã¾ããã
int rate = 2; [rate](int x) -> int { return x * ++rate; } // ã¨ã©ã¼ï¼rateå¤æ°ãæ¸ãæãããã¨ã¯ã§ããªã
ã³ãã¼ãã£ããã£ããå¤æ°ãã©ããã¦ãã©ã ãå¼å ã§æ¸ãæãããå ´åã¯ãã©ã ãå¼ãmutable修飾ãã¾ãã
[rate](int x) mutable -> int { return x * ++rate; } // OK
ã追è¨ãstd::reference_closureã¯ã©ã¹ã¯åé¤ããã¾ããã
ãåç
§ã©ã ãã
ã©ã ãå¼ãåç
§ç°å¢ã®ã¿ãæã¤å ´åãã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã¯std::reference_closureã¨ããã¯ã©ã¹ãç¶æ¿ããé¢æ°ãªãã¸ã§ã¯ãã«ãªãã¾ãã
ãã®å ´åããã£ããã£ããå¤æ°ãã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã®ã¡ã³ãå¤æ°ã«ãªãã®ã§ã¯ãªãã
ãã¬ã¼ã ãã¤ã³ã¿ã¨ãããã®ã使ç¨ãã¦ã¹ã³ã¼ããã®ããè¦ããã¨ãããã¨ãããããã«ãªãã¾ãã
ã¾ããã©ã ãå¼ã®ãã£ããã£ã»ããã1ã¤ä»¥ä¸åç §ãå«ãå ´åãã³ã³ããã¹ããããã¯ãæãããã¨ã®ã¯ãã¼ã¸ã£ãªãã¸ã§ã¯ãã®å®è¡ã¨ã³ãã¼ã®åä½ã¯æªå®ç¾©ã§ãã
#include <functional> std::reference_closure<int(int)> foo() { int n = 3; return [&n](int i) -> int { return n + i; }; } foo()(2); // æªå®ç¾©ã®æ¯ãèã
std::reference_closureã¯ãã©ã ãå¼ãé¢æ°ã«æ¸¡ãéã«ãåç §ç°å¢ã®ã¿ãæã¤ã©ã ãå¼ã¨ãã以å¤ã®ã©ã ãå¼ã§ãªã¼ãã¼ãã¼ãããããã«ä½¿ç¨ãããã¨ãã§ãã¾ãã
void foo(std::reference_closure<void(void)>); void foo(std::function<void(void)>); foo([&]{}); // reference_closureã®æ¹ãå¼ã°ãã foo([=]{}); // functionã®æ¹ãå¼ã°ãã
N2550 Lambda Expressions and Closures: Wording for Monomorphic Lambdas (Revision 4)
N2658 Constness of Lambda Functions (Revision 1)