web-dev-qa-db-ja.com

C ++ 11無名関数内からローカル変数にアクセスするにはどうすればよいですか?

私はベクトル(重み)で単純な正規化を行っており、STLアルゴリズムを利用してコードを可能な限りクリーンにしようとしています(これはforループでは非常に簡単です):

float tot = std::accumulate(weights.begin(), weights.end(), 0.0);
std::transform(weights.begin(), weights.end(), [](float x)->float{return(x/tot);});

現在、totは無名関数には表示されないため、コンパイルされません。ローカル変数を無名関数に表示するための最良の方法は何ですか?

30
bd1

閉鎖が必要です。

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

この場合、totは値によってキャプチャされます。 C++ 11ラムダは、次の方法によるキャプチャをサポートしています。

  1. [x]
  2. 参照 [&x]
  3. 参照により現在スコープ内にある変数[&]
  4. 3と同じですが、値によって[=]

上記のいずれかをコンマ区切りのリストに混在させることができます[x, &y]

48
pmr

ラムダは、アンビエントスコープから変数を「キャプチャ」できます。

[ ..., N, ... ](int a, int b) -> int  { return (a + b) * N; }
 ^^^^^^^^^^^^^  ^^^^^^^^^^^^     ^^^^
 captured vars  local params     ret.type

値または参照でキャプチャできます。また、特別な構文[=]および[&]を使用して、アンビエントスコープからanything、つまり実際に使用するものをキャプチャできます。

8
Kerrek SB

「キャプチャリスト」にtotを追加する必要があります。

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

または、capture-defaultを使用して、totを暗黙的にキャプチャすることもできます。

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [=](float x)->float{return(x/tot);});
2
Mankarse