c++ - ラムダ閉包左辺値は右辺値参照パラメーターとして渡すことができます




lambda closures (2)

ケース1が機能する仕組みと理由

foo を呼び出すには、 右辺値参照に バインドする std::function<void()> インスタンスが必要です。 std::function<void()> は、 void() 署名と互換性のある 呼び出し可能なオブジェクト から構築 できます

最初に、一時 std::function<void()> オブジェクトが []{} から構築されます。 使用されるコンストラクターは here で#5であり、クロージャーを std::function インスタンスにコピーします:

template< class F >
function( F f );

std::move(f) ターゲットを初期化します。 f が関数へのヌルポインターまたはメンバーへのヌルポインターの場合、 *this は呼び出し後は空になります。

次に、一時 function インスタンスが右辺値参照にバインドされます。

関数が返された後のfn1クロージャの状態は何ですか?

前と同じ、 std::function インスタンスにコピーされたため。 元の閉鎖は影響を受けません。

lvalue ラムダクロージャーは常に rvalue 関数のパラメータとして渡すことができることがわかりました。

次の簡単なデモをご覧ください。

#include <iostream>
#include <functional>

using namespace std;

void foo(std::function<void()>&& t)
{
}

int main()
{
    // Case 1: passing a `lvalue` closure
    auto fn1 = []{};
    foo(fn1);                          // works

    // Case 2: passing a `lvalue` function object
    std::function<void()> fn2 = []{};
    foo(fn2);                          // compile error

    return 0;
}

ケース2は標準的な動作です(デモンストレーションの目的で std::function を使用しましたが、他のタイプでも同じように動作します)。

ケース1が機能する仕組みと理由 関数が返された後の fn1 クロージャの状態は何ですか?


関数が返された後のfn1クロージャの状態は何ですか?

fn1 は何もキャプチャしないため、ステートレスです。

ケース1が機能する仕組みと理由

引数は、参照される右辺値である型とは異なる型であるため機能します。 タイプが異なるため、暗黙的な変換が考慮されます。 ラムダは、この std::function 引数に対してCallableであるため、 std::function のテンプレート変換コンストラクターを介して暗黙的にラムダに変換でき std::function 。 変換の結果はprvalueであるため、右辺値参照にバインドできます。





rvalue-reference