2012-07-17 4 views
6

C++ 11標準は、(私が持っているか、少なくとも、バージョン - ない最終1)言う:とラムダ式のため暗黙の「ラムダから関数へのポインタ変換」は、静的メンバーの「参照による」キャプチャを禁止するのはなぜですか?

閉鎖型の無ラムダキャプチャは、公共 を持っています非仮想非明示的const変換関数をポインタ と同じパラメータと戻り値の型を持つ関数として、クロージャ 型の関数呼び出し演算子として機能させます。

なぜ私は、ステートフルラムダから関数ポインタを得ることができないのですが、関数ポインタはそれ自身でデータを保持することができないので、私は理解しています。

しかし、キャプチャされたオブジェクトが静的メンバ/静的変数に過ぎない場合、キャプチャされたオブジェクトへの参照は関数自体でハードワイヤードできるため、このような制限はありません。

struct A { 
    static int count = 0; 
    void foo() { 
     static int bar = 0; 
     auto fun = [&]()->void { 
      count++; 
      bar++; 
     }; 
     void(*ptrFun)(); 
     ptrFun = fun; // forbidden by the quoted wording 
    } 
}; 

なぜラムダをファンクションポインタに変換することができないのですか?私は何かを逃しているのですか、委員会はこの特定の点を忘れていますか?

+1

私は、コンパイル時に何がキャプチャされているかについて何かを証明できるようにすることを避けることを推測します。 – Flexo

+0

コンパイラは、(自動[&]を使用して)使用されるとすぐに変数を自動的にキャプチャすることができるため、静的メンバであるかグローバルであるかをチェックする作業は必要ありません以前に宣言された –

+0

実際に私はどのコンパイラでもテストしていません(関数ポインタ変換をサポートしていないMSVC10しかありません)。私はそれがGCC拡張だと思いますか?とにかく、私の質問です:それは標準で許可されています(多分私は何かを逃した)?いいえ、なぜそれは禁じられていますか(多分私が知らない技術的な制限があります)? –

答えて

9

A::countは、まったくキャプチャする必要はありません。 thisとローカル変数のみがキャプチャされる必要があります。静的記憶期間(例えば、静的データメンバ、名前空間スコープ変数、または関数ローカル静的変数)を有する変数は、「一意」であるので、キャプチャする必要はない。このような各変数には、正確に1つのインスタンスが存在するため、オブジェクトへの参照を取得する必要はありません。

ラムダからデフォルトキャプチャを削除して([&]から[]に変更)、countを定義すると、エラーなしでコンパイルする必要があります。 (私はVisual C++ 2012 RCとg ++ 4.5.1の両方がコードを受け入れることを確認しましたが、インライン初期化をcountに移動するだけでした。どちらのコンパイラもC++ 11の機能をまだサポートしていないからです。 )

+0

もちろん...私は今、愚かな気分です:)しかし、静的なローカル変数をキャプチャしたいのですが? –

+0

同様の理由で、キャプチャする必要もありません。各静的ローカル変数は「一意」であり、既知のアドレスを持ちます。私は、静的な記憶期間を持つ変数を参照する答えを修正しました。 (VC11とg ++ 4.5.1は両方とも、名前空間スコープ変数、静的データメンバー、または関数型変数として 'count'を持つプログラムを受け入れます)ローカル静的)。 –

+0

私はそれが許されていたことを知らなかった、ありがとう! –