以下の場合を考える。
class Foo
{
int x ;
public :
void f()
{
// f()の中で百個の自動変数を使う。
int val001, val002, val003, /*...*/ val100 ;
// lambda expression
[&]{// #1
// ここで、valXXXなる一連の変数を全部使いたい。
// さらにlambda expression
[&]
{// #2
// ここで、#1の直前のメンバ関数であるf()のthisを使いたい。
// と同時に、valXXXなる一連の変数も使いたい。
this->x = val001 ;
}() ;
}() ;
}
} ;
上記のコードは、おそらく失敗するであろうと思われる。というのも、lambdaは直前の自動変数しかキャプチャできないからだ。#1のキャプチャリストに、明示的に書いたとしても、#2で使うことは出来ない。なぜならば、キャプチャした変数は、lambdaのクロージャオブジェクトのメンバ変数という扱いだからだ。従って、上記コードの正しい例はこうなる、と思う。
class Foo
{
int x ;
public :
void f()
{
// f()の中で百個の自動変数を使う。
int val001 = 1, val002 = 2, val003 = 3, /*...*/ val100 = 100 ;
// lambda expression
[&]{// #1
auto auto_val001 = val001 ;
// 使う必要のあるvalXXXを、ここで全部明示的に自動変数に代入。
// さらにlambda expression
[&]
{// #2
this->x = auto_val001 ;
}() ;
}() ;
}
} ;
たとえ、#2でthisをキャプチャしても、それは#1のlambdaのクロージャオブジェクトのthisにはならない。#1の直前のメンバ関数のthisになる。したがって、this->val001などとやって、#2から#1のキャプチャした変数を全部使うなどと言う抜け道はない。もし本当に使いたいのであれば、#1のcompound-statement内で、地道に必要な変数を全部、自動変数に代入してやる必要がある。
どうも、lambdaのネストは使いづらいな。
追記:#2のthisは#1のキャプチャしたthisであり、つまり#1を直接包括するメンバ関数のthisなので、thisを自動変数にする必要はない。
No comments:
Post a Comment