C++11, Lambda Expressions #2
Short Articles 2012. 2. 1. 18:52+ lambda-declarator
(파라미터 선언 절) mutable exception-specification attribute-specification trailing-return-type
의 형식으로 작성되고,
이 중에서 (파라미터 선언 절) 외의 부분들은 필요에 따라 적어주면 되는 부분들입니다.
lambda-declarator 에 포함된 사항들은 C++ lambda 의 새롭게 추가된 사항이 아닌 기존 C++ 에 이미 정의된 사항들 이므로 자세한 내용은 생략 하겠습니다.
간단한 예시 코드,
이 람다식이 포함하는 closure object 는 ecode 변수를 copy 로 capture 합니다.
mutable 키워드는 capture 를 compound-statement 내에서 수정 가능함을 나타내고,
뒤따라오는 throw(int) 는 int type 의 예외를 던진다는 것을 알립니다. ->int 는 compound-statement 의
리턴 타입이 int 형임을 지정합니다.
[=](char const *s) throw(int) ->int ... 와 같이 mutable 키워드를 지정하지 않는 경우
closure 에서 public 으로 선언(정의)되는 function call operator 는 기본 const 입니다.
local-lambda expression
local lambda expression 의 영향 범위는 자신의 한겹 위쪽 블럭과 아래쪽으로 포함되는 영역 입니다.
(함수와 함수의 파라미터를 포함해서..)
이 유효 범위 사이에는 또다른 람다 표현식이 끼어들 수도 있습니다.
위 코드에서 람다 표현식의 범위는 PrintPoint 함수의 블럭과 표현식이 포함하고 있는 출력 코드 부분입니다.
이 경우 name 은 local lambda expression 의 유효 범위 밖에 있기 때문에 에러가 납니다.
이 때에는 명시적으로 this 를 capture 하거나 PrintPoint 의 지역 변수로 const char* 하나를 선언해서
name 의 값을 받은 후 이것을 명시적으로 capture 하는 식으로 에러를 피할 수 있습니다.
lambda 표현식의 capture-list 에 대한 name look up 은 일반적인 unqualified name look up
(:: , std:: , boost:: 등으로 특정 짓지 않은 entitiy 에 대한 name look up) 에 따릅니다.
각각의 룩업은 local lambda expression 의 유효 범위 내에서 automatic storage duration 으로
automatic storage duration :
자동으로 생명주기가 관리되는 것들을 말한다. variable with automatic storage duration 이라 하면,
C++ 에서는 주로 stack 에 생성되는 지역 변수등을 일컫는다.
람다 표현식이 capture-default 를 포함하고 표현식의 odr 사용이 this 나 automatic storage duration
변수 그리고 odr이 사용된 entity 가 명시적으로 캡처(explicitly capture)되지 않았다면,
odr이 사용된 entity 는 임시적으로 캡처(implicitly capture) 되었다고 합니다.
다음은 표준 문서에 나오는 implicitly capture 에 대한 예제 코드 입니다.
코드 작성과 테스트는 eclipse with g++4.6.2 로 했습니다.
이 코드를 컴파일하면 다음과 같은 에러를 보게 됩니다.
../src/hello.cpp: In lambda function:
../src/hello.cpp:38:18: error: 'j' is not captured
../src/hello.cpp: In lambda function:
../src/hello.cpp:39:14: error: 'n' is not captured
../src/hello.cpp:43:11: error: 'i' is not captured
../src/hello.cpp: In lambda function:
../src/hello.cpp:45:5: error: unable to deduce 'auto' from '<expression error>'
N 과 M 은 m1 에 의해서 implicitly capture 되었기 때문에 괜찮지만,
j 는 m3 에 의해서 캡처 되지 않았고 n 은 m4 에 의해서는 implicitly capture 되지만
m4 를 둘러싸고 있는 m3 가 n 을 캡처 하지 않았기 때문에 에러입니다.
그리고 i 는 유효범위 밖에 있으므로 역시 에러가 나고 있습니다.
다음과 같이 명시적으로 n, j 를 캡처하고 x += i; 를 주석 처리 하면
에러없이 컴파일 되는 것을 확인할 수 있습니다.
아무튼 람다 표현식이 기본인자로 쓰일 경우
void foo(int = ( []{ return 0;}() ));
별다른 내용은 없습니다.
entity 가 explicitly capture 되었고 '&' 를 포함하지 않으면,
이 entity 는 copy 로 캡처 되었다고 합니다.
by copy 로 capture 캡처된 entity 는 closure 의 non-static unnamed 데이터 멤버로 선언됩니다.
이 때, 선언되는 순서에 정해진 규칙은 없습니다. entity 가 객체나 그 밖의 타입에 대한 참조가
아닐 경우 이렇게 되며, int &p = value; 에서의 p 같은 참조 변수는 captured by copy 되지 않습니다.
m1 이 by copy 로 캡처한 entity 는 m1 의 closure 타입의 non-static data member 에 대응되는 것으로
m2 에 캡처됩니다. 그리고 m1 이 by reference 로 캡처한 entity 는 m1 이 캡처한 것과 동일한 entity 로
m2 가 캡처합니다.
이 코드의 결과 값은 다음과 같습니다.
123234
표준 문서에 몇 가지 추가적인 사항에 대한 설명이 나오므로 더 자세한 사항을 원하시는 분은
표준 명세를 찾아보시기 바랍니다.
'Short Articles' 카테고리의 다른 글
C++ Template, Expression Templates #2 (0) | 2012.02.17 |
---|---|
C++ Basic Concept, Storage Duration (0) | 2012.02.10 |
C++ Template, Expression Templates #1 (3) | 2012.02.08 |
C++ Basic Concept, One definition rule (ODR) (2) | 2012.02.07 |
C++11, Lambda Expressions #1 (2) | 2012.01.30 |