2011-07-13 10 views
4

ポイントをセクション5.1.2、パラ6:ラムダ式: ラムダ式:n3290 ISOドラフトからn3290ドラフト

  "The closure type for a lambda-expression with no 
     lambda-capture has a public non-virtual non-explicit const 
     conversion function to pointer to function having the same 
     parameter and return types as the closure type’s function 
     call operator. The value returned by this conversion 
     function shall be the address of a function that, when 
     invoked, has the same effect as invoking the closure 
     type’s function call operator." 

いずれかの例でこの点をしてください説明できますか?

+0

これの特定の部分は混乱していますか?あなたが理解していない用語がありますか?あなたは、必要な行動が何であるか理解していませんか? –

+0

@ James:typedef int(* pf)(int); int callback(pf func){returnfunc(3);} pf func = [](int k) - > int {k--;} return k;}; – user751747

+0

@ジェームズ:上記の..exampleは上記のステートメントを表しています...ポイントについてはちょっと混乱しています。 "クロージャタイプの関数呼び出し演算子を呼び出すのと同じ効果" ..しかし、プログラムの観点から証明することはできません。.way – user751747

答えて

4

短い答え

これだけ何もキャプチャしていないラムダを同じシグネチャの関数ポインタに変換できることを意味します。

auto func = [](int x) { return x * 2; }; 
int (*func_ptr)(int) = func; // legal. 

int y = func_ptr(2); // y is 4. 

キャプチャm akesは、それは違法:

int n = 2; 
auto func = [=](int x) { return x * n; }; 
int (*func_ptr)(int) = func; // illegal, func captures n 

長い答え

ラムダは、ファンクターを作成するための速記です:

auto func = [](int x) { return x * 2; }; 

は同等です:この場合

struct func_type 
{ 
    int operator()(int x) const { return x * 2; } 
} 

func_type func = func_type(); 

func_type 「クロージャタイプ」and operator()は「関数呼び出し演算子」です。あなたは、ラムダのアドレスを取得する場合、それはあなたがoperator()は、静的に宣言かのようであり、そのアドレスを取る、他の関数のように:

struct func_type 
{ 
    static int f(int x) { return x * 2; } 
} 

int (*func_ptr)(int) = &func_type::f; 

あなたは変数を撮影しているとき、彼らはfunc_typeのメンバーになります。 operator()は、これらのメンバーに依存し、それは静的にすることはできません。

struct func_type 
{ 
    int const m_n; 

    func_type(int n) : m_n(n) {} 
    int operator()(int x) const { return x * m_n; } 
} 

int n = 2; 
auto func = func_type(n); 

通常の関数は、メンバ変数の概念はありません。この考えを踏まえて、lambdaはメンバ変数も持たない場合にのみ、通常の関数として扱うことができます。

+0

コンパイラがno captureを診断するかどうか知っていますか?たとえば、 '[=](int x){return x * 2;}'と書くと、値で取り込むように指定しても、何もキャプチャしません。 –

+0

[=]は単にデフォルトキャプチャを変更するだけです。実際に何もキャプチャしない限り、関数ポインタに変換することはできます。 –

+0

@ Cory what about this ... statement "この変換関数によって返される値は、呼び出されたときにクロージャー型の関数呼び出し演算子を呼び出すのと同じ効果がある関数のアドレスでなければなりません。" 。これもまた – user751747

2

これは、新しいC++ 0x lambdaが(同じ署名を持つ)関数ポインタへの変換演算子を持っていると(おおよそ)言っています。その関数ポインタを呼び出すと、同じパラメータが渡されたラムダを呼び出すようなものになります。 「ノーラムダ・キャプチャーと」

...ないラムダキャプチャとラムダ式...

はあなたが含む範囲から任意の変数をキャプチャし、それはなかったことを意味し自己完結型です。この宣伝文から

、私はあなたが(ローカルスコープから例えば)変数を撮影した場合、あなたが変換を行うことができないことを考えています:

// this is fine... 
std::vector<int> some_list; 
int total = 0; 
std::for_each(some_list.begin(), some_list.end(), [&total](int x) { 
    total += x; 
}); 

// so is this... 
int total = 0; 
auto someLambda = [](int x) { return x * 5; }; 
int (*pointerToLambda)(int) = someLambda; 
someFunction(pointerToLambda); 

// this won't work, because of capture... 
int total = 0; 
auto someLambda = [&total](int x) { total += x; return total; }; 
int (*pointerToLambda)(int) = someLambda; 
someFunction(pointerToLambda); 
+0

何かを捕まえると保証できません。捕捉された値はオブジェクトに格納されるので、 'operator()'は静的にすることはできませんので、静的/非メンバ関数ポインタに変換することはできません。 –