[c++] C ++ 11에서 “auto”로 추론 할 때 람다 유형은 무엇입니까?
람다의 유형은 함수 포인터라는 인식이있었습니다. 다음 테스트를 수행했을 때 잘못된 것으로 나타났습니다 ( demo ).
#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
assert(typeid(pFptr) == typeid(pAuto)); // assertion fails !
}
위의 코드에 포인트가 없습니까? 그렇지 않으면 키워드로 typeof
추론 할 때 람다 식은 auto
무엇입니까?
답변
람다 식의 유형이 지정되지 않았습니다.
그러나 그들은 일반적으로 functors에 대한 단순한 구문 설탕입니다. 람다는 functor로 직접 변환됩니다. 내부의 모든 []
것은 생성자 매개 변수 및 functor 객체의 멤버로 바뀌며 내부의 매개 변수 ()
는 functor ‘s의 매개 변수로 바뀝니다 operator()
.
변수를 캡처하지 않는 람다는 (의 안에는 없음 []
) 함수 포인터 로 변환 할 수 있습니다 (MSVC2010은 컴파일러 인 경우 이것을 지원하지 않지만이 변환은 표준의 일부입니다).
그러나 람다의 실제 유형은 함수 포인터가 아닙니다. 지정되지 않은 functor 유형입니다.
답변
함수 호출 연산자를 오버로드하는 고유 한 명명되지 않은 구조입니다. 람다의 모든 인스턴스는 새로운 유형을 도입합니다.
캡처되지 않는 람다의 특수한 경우 구조는 함수 포인터로 암시 적으로 변환됩니다.
답변
[C++11: 5.1.2/3]:
의 타입 람다 식 (또한 밀폐 객체의 유형) 의 고유 이름 불유합 클래스 타입 – 착신 폐쇄 형 그 특성 설명한다 -. 이 클래스 유형은 집계 (8.5.1)가 아닙니다. 클로저 유형은 해당 lambda-expression 을 포함하는 가장 작은 블록 범위, 클래스 범위 또는 네임 스페이스 범위에서 선언됩니다 . [..]
이 절에서는이 유형의 다양한 속성을 나열합니다. 주요 내용은 다음과 같습니다.
[C++11: 5.1.2/5]:
람다 식 의 클로저 형식 에는inline
매개 변수와 반환 형식이 각각 람다 식 의 매개 변수 선언 절 과 후행 반환 형식으로 설명되는 공용 함수 호출 연산자 (13.5.4)가 있습니다. [..]
[C++11: 5.1.2/6]:
A의 폐쇄 형 람다 표현 아니오 람다 캡처는 폐쇄 형의 함수 호출 연산자와 같은 매개 변수와 리턴 유형을 가진 함수 포인터에 공개되지 않은 가상이 아닌 명시 적 const를 변환 기능이 있습니다. 이 변환 함수에 의해 리턴 된 값은 호출 될 때 클로저 유형의 함수 호출 연산자를 호출하는 것과 동일한 효과를 갖는 함수의 주소입니다.
마지막 구절의 결과는 당신이 변환을 사용하는 경우, 당신은 할당 할 수있을 것,이다 LAMBDA
에 pFptr
.
답변
#include <iostream>
#include <typeinfo>
#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
long (*pFptr)(int) = LAMBDA; // ok
auto pAuto = LAMBDA; // ok
std::cout<<typeid( *pAuto ).name() << std::endl;
std::cout<<typeid( *pFptr ).name() << std::endl;
std::cout<<typeid( pAuto ).name() << std::endl;
std::cout<<typeid( pFptr ).name() << std::endl;
}
함수 유형은 실제로 동일하지만 람다는 새 유형을 도입합니다 (예 : functor).
답변
또한 람다는 함수 포인터로 변환 할 수 있습니다. 그러나 typeid <>는 람다와 일반 함수 포인터에 따라 다르지 않은 객체를 반환합니다. 따라서 typeid <> 테스트는 유효한 가정이 아닙니다. 일반적으로 C ++ 11은 유형 지정에 대해 걱정하지 않으려 고합니다. 주어진 유형이 대상 유형으로 변환 가능한지 여부는 중요합니다.
답변
에서 실용적인 솔루션 어떻게 내가 클래스 멤버로 부스트 :: 바인드 객체를 저장할 수 있습니까? , boost::function<void(int)>
또는을 시도하십시오 std::function<void(int)>
.