6

C++ 11標準は次のように述べています(または少なくとも、私が持っているバージョン-最終バージョンではありません):

ラムダ キャプチャのないラムダ式のクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメーターと戻り値の型を持つ関数へのポインターへの public 非仮想非明示的な 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
    }
};

前者がステートレスになるとすぐに、ラムダを関数ポインターに変換することが常に可能ではないのはなぜですか? 私は何かを見逃していますか、それとも委員会はこの特定の点を忘れていましたか?

4

1 に答える 1

9

A::countキャプチャする必要はまったくありません。ローカル変数のみthisをキャプチャする必要があります。静的ストレージ期間を持つ変数 (静的データ メンバー、名前空間スコープ変数、関数ローカル静的変数など) は "一意" であるため、キャプチャする必要はありません。このような各変数のインスタンスは 1 つだけ存在するため、オブジェクトへの参照を取得する必要はありません。

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

于 2012-07-17T23:17:59.493 に答える