캡처 할 수없는 람다는 표준에 따라 비어 있습니까?


12

템플릿 함수에서 다른 람다에서 빈 (캡처가없는) 람다를 식별하는 방법을 찾고 있습니다. 나는 현재 C ++ 17을 사용하고 있지만 C ++ 20 답변도 궁금합니다.

내 코드는 다음과 같습니다

template<typename T>
auto func(T lambda) {
    // The aguments of the lambdas are unknown

    if constexpr (/* is captureless */) {
        // do stuff
    }
}

C ++ 표준 (17 또는 20)에서 함수 포인터로 변환 할 수있는 캡처없는 람다는 수율을 보장 할 std::is_empty수 있습니까?

이 코드를 예로 들어 보겠습니다.

auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures

static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed?

라이브 예


2
템플릿이 아닌 람다 만 신경 쓰면 SFINAE를 사용하여 함수 포인터 ( +lambda) 로의 변환이 올바른지 확인할 수 있습니다 .
HolyBlackCat

@HolyBlackCat 나는 그것에 대해 생각했지만 MSVC는 변환 연산자를 오버로드했기 때문에 허용하지 않습니다.
기 illa Racicot

@GuillaumeRacicot MS는 사용 가능한 모든 통화 규칙에 대해 별도의 변환 연산자를 제공합니다. 하나를 선택하고 람다를 비슷한 함수 포인터로 변환하고 성공 또는 실패 여부를 확인하십시오.
Remy Lebeau

+여기 에서 작동하는 것 같습니다 .
HolyBlackCat

답변:


13

사실,이 표준은 람다가 선언과 일치하지 않는 크기를 가질 수있는 권한을 명시 적으로 부여합니다. [expr.prim.lambda.closure] / 2 개 상태

클로저 유형은 해당 람다식이 포함 된 가장 작은 블록 범위, 클래스 범위 또는 네임 스페이스 범위에서 선언됩니다. [참고 : 클로저 유형 ([basic.lookup.argdep])과 관련된 네임 스페이스 및 클래스 집합을 결정합니다. 람다 선언자의 매개 변수 유형은 이러한 관련 네임 스페이스 및 클래스에 영향을 미치지 않습니다. — 종료 참고] 클로저 유형은 집계 유형이 아닙니다. 구현은 변경에 의한 것 이외의 프로그램의 관찰 가능한 동작을 변경하지 않는 한 아래에 설명 된 것과 다르게 폐쇄 유형을 정의 할 수 있습니다.

  • 클로저 타입의 크기 및 / 또는 정렬

  • 클로저 유형이 간단하게 복사 가능한지 ([class.prop]) 또는 (2.3)

  • 클로저 유형이 표준 레이아웃 클래스인지 여부 ([class.prop])

구현시 rvalue 참조 유형의 멤버를 클로저 유형에 추가해서는 안됩니다.

강조 광산

따라서이를 통해 구현은 람다에 캡처가없는 경우에도 멤버를 제공 할 수 있습니다. 나는 어떤 구현도 가능하다고 생각하지 않지만 법적으로 그렇게 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.