Lambda 클로저 lvalue는 rvalue 참조 매개 변수로 전달 될 수 있습니다.

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함수가 반환 된 후 클로저 상태는 무엇입니까 ?



답변

사례 1은 어떻게, 왜 작동합니까?

호출 foo하려면 rvalue 참조에std::function<void()> 바인딩 된 인스턴스가 필요합니다 . 서명 과 호환되는 호출 가능한 객체 로 구성 할 수 있습니다 .std::function<void()>void()

먼저 임시 std::function<void()>객체는로 구성됩니다 []{}. 사용 된 생성자는 # 5 here 로 클로저를 std::function인스턴스에 복사합니다 .

template< class F >
function( F f );

로 대상을 초기화합니다 std::move(f). 경우 f회원에게 기능 또는 널 포인터에 NULL 포인터가, *this호출 후 비어 있습니다.

그런 다음 임시 function인스턴스는 rvalue 참조에 바인딩됩니다.


함수가 반환 된 후 fn1 클로저 상태는 무엇입니까?

std::function인스턴스 로 복사되었으므로 이전과 동일 합니다. 원래 폐쇄는 영향을받지 않습니다.


답변

람다는가 아닙니다 std::function. 참조는 직접 바인딩되지 않습니다 .

람다는 std::functions 로 변환 가능하기 때문에 사례 1이 작동합니다 . 이것은 복사 로 임시 std::function가 구체화 됨을 의미합니다 . 이 임시는 rvalue 참조에 바인딩 될 수 있으므로 인수가 매개 변수와 일치합니다. fn1

그리고 복사는 또한 fn1에서 발생하는 모든 것에 영향을받지 않는 이유 입니다 foo.


답변

함수가 반환 된 후 fn1 클로저 상태는 무엇입니까?

fn1 아무것도 캡처하지 않기 때문에 상태가 없습니다.

사례 1은 어떻게, 왜 작동합니까?

인수가 rvalue 참조 된 유형과 다른 유형이기 때문에 작동합니다. 유형이 다르기 때문에 암시 적 변환이 고려됩니다. 람다는이 인수에 대해 호출 가능하므로의 std::function템플릿 변환 생성자를 통해 암시 적으로 변환 할 수 std::function있습니다. 변환 결과는 prvalue이므로 rvalue 참조와 바인딩 될 수 있습니다.