Visual C++ 팀블로그에 C++0x에 대한 소개 자료중 람다(Lambda)에 관한 내용을 번역했습니다.
차후에 나머지도 번역해서 올리겠습니다.
번역이 만만치 않은 작업이근영....
원본 :
차후에 나머지도 번역해서 올리겠습니다.
번역이 만만치 않은 작업이근영....
원본 :
마이크로소프트 비절 스투디오 2010CTP(Community Technology Preview)에서는 C++ 0x에 포함된 lambdas, auto, static_assert,rvalue references 라는 4가지의 개념을 제공합니다. 여기서는 처음 세가지에 대해 이야기를 하겠습니다.
첫번째로 , 내용을 쓰기전..:
1. 이 포스트는 Visual C++ 라이브러리 개발자인Stephan T. Lavavej 님이작성했습니다. 그리고 Stephan T. Lavavej님이 위의 네가지 기능에 대한 구현을 담당하지 않았음을 밝힘니다.
2. 내용에서 VS 2010에서 Visual C++ 컴파일러를 VC10이라고 칭할 것 입니다(10은 2010의 약어가 아님).
3. C++0x는 아직 논의 중인 차세대 C++ 표준을 의미합니다.
(표준 위원회(The Standardization Committee) 2009에 C++09라는 이름으로 발표되기 원하지만 2010이나 더 걸릴수 있기 때문에 x를 붙였다는 조크도있다네요. C++98 과 C++03 는 현재 C++ 표준을 의미 합니다.(여기서 역사이야기는 하지 않고 2003년에 발표된 C++표준은 1998년에 발표된 C++에대한 단순한 “서비스팩” 이었고 대부분의 사람들은 이들의 차이점에 대해 무시하였죠. C++03 과 C++0x 는 완전히 다릅니다.
4. 나는 C++ 0x가 완벽하고 멋지게 구성하고 있을 표준 위원회(The Standardization Committee)에 감사를 표합니다. 그들은 또한 아래의 링크에 좋은 자료를 올려 두었습니다.
이제 본론으로 들어가겠습니다.
lambdas
C++0x에는 명명되지않은(unnamed) 함수객체(function objects)를 수동으로 선언과 정의를 하지않고, 이것을 포함하고 있는 함수객체(function objects)를 사용할 수 있는 “람다(lambda) 수식”이 있습니다.
아래는 람다를 사용한 "Hello, World" 예제 입니다. :
C:\Temp>type meow.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 meow.cpp > NUL && meow
0 1 2 3 4 5 6 7 8 9
|
[] 는 람다-소개자 (lambda-introducer) 입니다. 컴파일러에게 람다 수식이시작했다는 것을 알려주는 역할을 합니다. (int n)은 람다-매개변수-선언(lambda-parameter-declaration) 입니다. 어떤 명명되지 않은(unnamed) 함수 객체 클래스의 연산자( ()연산자를 의미하는듯)가 실행이 되어지는지 컴파일러에게 알려주는 역할을 합니다. 마지막으로 { cout << n << " "; } 는 복합-서술(compound-statement)부분이고 , 명명되지않은 함수 객체의 몸체(정의부) 입니다. 기본적으로 명명되지 않은 함수 객체의연산자는 void를 리턴합니다.
그러면 C++0x에서 쓰여진 람다를 현재 C++로 구현한다면 어떻게 구현되는지보겠습니다.
C:\Temp>type meow98.cpp
#include
#include
#include
#include
using namespace std;
struct LambdaFunctor {
void operator()(int n) const {
cout << n << " ";
}
};
int main() {
vector
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
for_each(v.begin(), v.end(), LambdaFunctor());
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 meow98.cpp > NUL && meow98
0 1 2 3 4 5 6 7 8 9
|
이제부터 “명명되지않은 함수 객체 클래스의 () 연산자는 void를 리턴한다” 를“람다는 void를 리턴한다”라고 말하겠습니다. 하지만, 람다 수식이 클래스를정의하고 생성하는 것은 중요하니 기억해 두세요.
물론, 람다의 복합-서술(compound-statement)구문은 여러줄로 쓸 수 있습니다.
C:\Temp>type multimeow.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
for_each(v.begin(), v.end(), [](int n) {
cout << n;
if (n % 2 == 0) {
cout << " even ";
} else {
cout << " odd ";
}
});
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 multimeow.cpp > NUL && multimeow
0 even 1 odd 2 even 3 odd 4 even 5 odd 6 even 7 odd 8 even 9 odd
|
그리고, 람다는 항상 void를 리턴 하지 않습니다. 만약 람다의 복합-서술(compound-statement)이 { return expression; }로 되어 있다면, 람다의리턴 타입은 자동으로 수식의 타입으로 만들어 줍니다.
C:\Temp>type cubicmeow.cpp
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
deque
transform(v.begin(), v.end(), front_inserter(d), [](int n) { return n * n * n; });
for_each(d.begin(), d.end(), [](int n) { cout << n << " "; });
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 cubicmeow.cpp > NUL && cubicmeow
729 512 343 216 125 64 27 8 1 0
|
여기서 n * n * n 는 int 타입이고 람다의 함수기 호출하는 ()연산자는 int를리턴합니다.
람다로 더 복작한 복합-서술(compound-statements)구문은 자동으로 리턴타입을 만들어 줄 수 없습니다. 아래 코드와 같이 리턴타입을 명시해 주어야 합니다.
C:\Temp>type returnmeow.cpp
#include
#include
#include
#include
#include
#include
using namespace std;
int main() {
vector
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
deque
transform(v.begin(), v.end(), front_inserter(d), [](intn) -> double {
if (n % 2 == 0) {
return n * n * n;
} else {
return n / 2.0;
}
});
for_each(d.begin(), d.end(), [](double x) { cout << x << " "; });
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 returnmeow.cpp > NUL && returnmeow
4.5 512 3.5 216 2.5 64 1.5 8 0.5 0
|
“-> double” 은 부가적으로 사용할 수 있는 람다-리턴-타입-구문(lambda-return-type-clause )입니다. 많은 개발자들이 왜 리턴 타입이 왼쪽에 오지 않는 건지 궁금해 하겠지만, lambda-introducer ( [] )가 앞에 있지않으면 컴파일러는 람다 문법의 시작을 알수 없기 때문입니다.
만약 람다 리턴 타입 구문을 쓰지 않으면 다음과 같은 컴파일 에러가 발생됩니다.
C:\Temp>cl /EHsc /nologo /W4 borkedreturnmeow.cpp
borkedreturnmeow.cpp
borkedreturnmeow.cpp(20) : error C3499: a lambda that has been specified to have a void return type cannot return a value
borkedreturnmeow.cpp(22) : error C3499: a lambda that has been specified to have a void return type cannot return a value
|
지금까지 보여준 람다는 데이터 멤버가 없는(stateless) 것들입니다.
여러분들은 지역변수를 “캡쳐링(capturing)”해서 데이터 멤버를 가지고 있는람다를 만들 수 있습니다. 비어있는 람다 소개자( lambda-introducer) []는 데이터 멤버가 없는 람다 라는 것을 의미 하고, 캡쳐리스트(capture-list)를지정하여 데이터 멤버를 가지는 람다를 만들 수 있습니다.
C:\Temp>type capturekittybyvalue.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 0;
int y = 0;
// op>>()는 입력 스트림에 개행 문자를 남겨야 하는데,
// 이건 꽤 귀찮으므로 쓰지 않을 것을 추천합니다.
// 대신 라인을 읽거나 읽어서 파싱하는 루틴을 만들고
// 싶다면getline(cin,str)함수를 사용하세요.
// 여기서는 간단하게 쓰기 위해 op>>()를 썼습니다.
cout << "Input: ";
cin >> x >> y;
v.erase(remove_if(v.begin(), v.end(), [x, y](int n) {return x < n && n < y; }), v.end());
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 capturekittybyvalue.cpp > NUL && capturekittybyvalue
Input: 4 7
0 1 2 3 4 7 8 9
|
캡쳐 리스트를 정의하지 않으면 아래의 오류 코드가 발생됩니다.
C:\Temp>cl /EHsc /nologo /W4 borkedcapturekittybyvalue.cpp
borkedcapturekittybyvalue.cpp
borkedcapturekittybyvalue.cpp(27) : error C3493: 'x' cannot be implicitly captured as no default capture mode has been specified
borkedcapturekittybyvalue.cpp(27) : error C3493: 'y' cannot be implicitly captured as no default capture mode has been specified
|
(기본(default) 캡쳐에 대한 설명은 나중에…)
람다 수식은 기본적으로 명명되지 않은 함수 객체 클래스를 정의 한다는 것을기억해두시길 바랍니다. 복합-서술(compound-statement) 구문인 { return x < n && n < y; } 클래스의 ()연산자 함수 몸체에 해당됩니다.
어휘상 복합-서술(compound-statement) 구문이 어휘상 main() 함수 내부에있지만 개념상 main()함수 외부에 존재 하는 것 입니다. 그래서 main() 함수내부에 있는 지역변수를 바로 사용할 수 없고 람다 내부에서 캡쳐하여 사용해야합니다.
아래 예제는 위의람다 캡쳐 예제를 현재 C++ 표준으로 구현한 것 입니다.
C:\Temp>type capturekittybyvalue98.cpp
#include
#include
#include
#include
#include
using namespace std;
class LambdaFunctor {
public:
LambdaFunctor(int a, int b) : m_a(a), m_b(b) { }
bool operator()(int n) const { return m_a < n && n < m_b; }
private:
int m_a;
int m_b;
};
int main() {
vector
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 0;
int y = 0;
cout << "Input: ";
cin >> x >> y; // EVIL! <<- 이러면 안된다는 말입니다..
v.erase(remove_if(v.begin(), v.end(), LambdaFunctor(x, y)), v.end());
copy(v.begin(), v.end(), ostream_iterator
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 capturekittybyvalue98.cpp > NUL && capturekittybyvalue98
Input: 4 7
0 1 2 3 4 7 8 9
|
여기서, 캡쳐의 의미가 “값에 의한(전달)” 이라는 것이 명확하게 알 수 있습니다. 지역변수의 복사본이 함수객체 내부 함수에 저장 되는 것을 볼 수 있습니다.
이는 함수 객체가 캡쳐하기 위해 생성된 지역변수 보다 더 오래 남을 수 있게 합니다.
아래 사항들을 알아 두세요.
(a) 함수호출 연산자( ()연산자 )는 기본적으로 const 이기 때문에, 캡쳐된 복사본은 람다 내부에서 수정될 수 없습니다.
(b) 어떤 객체는 복사하기 비용이 많이 듭니다.
(c) 지역변수를 변경하면 캡쳐된 복사본에는 아무런 영향을 없습니다. (값에의한 전달에 관한 내용).
이 부분은 다음에 필요할 때 이야기 하겠습니다.
캡쳐하고 싶은 지역변수들을 모두 지정하는 것 대신 “값에 의한 복사로 모두 캡쳐” 할 수 있습니다. 이것을 가능하게 하는 문법이 람다 소개자(lambda-introducer) 인 “ [=] “ 입니다. ( capture-default 인 ‘=’ 는 여러분이 대입연산자나 복사 초기화 Foo foo = bar 로 생각하게 하기 위함입니다;
사실 복사는 위의 예제에서 m_a(a) 같이 한번에 초기화 하기 위해 만들어 졌습니다.
C:\Temp>type defaultcapturekittybyvalue.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 0;
int y = 0;
cout << "Input: ";
cin >> x >> y; // EVIL!
v.erase(remove_if(v.begin(), v.end(), [=](int n) { returnx < n && n < y; }), v.end());
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
}
C:\Temp>cl /EHsc /nologo /W4 defaultcapturekittybyvalue.cpp > NUL && defaultcapturekittybyvalue
Input: 4 7
0 1 2 3 4 7 8 9
|
컴파일러는 람다 구문 내에 있는 x와 y를 보고, main()함수에 있는 x와 y의 값을 캡쳐 합니다.
위에서 (a)항목에서 말한 람다의 함수 호출 연산자( () 연산자) 가 기본적으로const이기 때문에 캡쳐한 복사본(원본)을 수정할 수 없지만, 람다 ()연산자 함수 내부에서 mutable(변하기 쉬운) 키워드를 사용하여 non-const로 만들면됩니다.
C:\Temp>type capturekittybymutablevalue.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 1;
int y = 1;
for_each(v.begin(), v.end(), [=](int& r) mutable {
const int old = r;
r *= x * y;
x = y;
y = old;
});
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
cout << x << ", " << y << endl;
}
C:\Temp>cl /EHsc /nologo /W4 capturekittybymutablevalue.cpp > NUL && capturekittybymutablevalue
0 0 0 6 24 60 120 210 336 504
1, 1
|
v에 있는 각 값에 이전의 x,y곱을 곱하는 동작을 합니다.
(이전의 모든 요소들과 곱해주도록 partial_sum() 함수나, 이전의 요소들과바로 곱해주도록 adjacent_difference() 함수를 이용해서 구현할수 가 없어서예제처럼 구현이 되어있습니다.) 위에서 말한 항목 “(d) 캡쳐된 복사본을 원본의 지역변수에 적용되지 않는다” 를 기억하세요.
위에 (b),(C),(d)의 약속을 우회할 방법을 알고 싶다면, 복사를 하지 않고 람다내부에서 값을 변경하는 것을 관찰하는 방법, 람다함수 내부에서 값을 바꿀 수있지 않을까요? 이럴 경우 참조(reference)로 값을 캡쳐하는 방법을 생각 했을겁니다. 이렇게 하는 방법은 람다-소개자(lambda introducer)를 [&x, &y]로하면 됩니다. ( [&x, &y] 를 X& x, Y& y로 생각하세요. 포인터의 전달이 아닌참조(Reference)입니다.) :
C:\Temp>type capturekittybyreference.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 1;
int y = 1;
for_each(v.begin(), v.end(), [&x, &y](int& r) {
const int old = r;
r *= x * y;
x = y;
y = old;
});
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
cout << x << ", " << y << endl;
}
C:\Temp>cl /EHsc /nologo /W4 capturekittybyreference.cpp > NUL && capturekittybyreference
0 0 0 6 24 60 120 210 336 504
8, 9
|
위의 예제 capturekittybymutablevalue.cpp 와 다른 점은
(1)람다-소개자 모양( lambda-introducer) [&x, &y]
(2) mutable 키워드가 없습니다.
(3) main()함수 지역 변수 x,y의 값이 람다함수 내부에서 변경된 것이main()함수에서도 적용되었습니다.
, 이 세가지 입니다.
위의 코드를 현재 C++로 구현 한다면 아래와 같이 구현할 수 있습니다.:
C:\Temp>type capturekittybyreference98.cpp
#include
#include
#include
#include
#include
using namespace std;
#pragma warning(push)
#pragma warning(disable: 4512) // assignment operator could not be generated
class LambdaFunctor {
public:
LambdaFunctor(int& a, int& b) : m_a(a), m_b(b) { }
void operator()(int& r) const {
const int old = r;
r *= m_a * m_b;
m_a = m_b;
m_b = old;
}
private:
int& m_a;
int& m_b;
};
#pragma warning(pop)
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int x = 1;
int y = 1;
for_each(v.begin(), v.end(), LambdaFunctor(x, y));
copy(v.begin(), v.end(), ostream_iterator
cout << endl;
cout << x << ", " << y << endl;
}
C:\Temp>cl /EHsc /nologo /W4 capturekittybyreference98.cpp > NUL && capturekittybyreference98
0 0 0 6 24 60 120 210 336 504
8, 9
|
(람다를 사용하면 , 컴파일러는 자동으로 C4512 경고를 꺼줍니다.)
지역 변수를 참조로 캡쳐하면, 함수 객체는 참조(reference)를 자신의 참조(reference) 멤버변수에 저장합니다.
이렇게 하면 함수 객체 () 함수에서 변경된 값이 적용이 되는 겁니다.
(함수 객체의 ()함수 가 const인 것에 주의하세요. 우리는(VC++ 컴파일러팀) mutable이라 하지 않습니다. const를 붙인 것은 단순히 함수객체의 멤버 데이터의 변경을 막기 위함 입니다. 멤버데이터들은 참조하는 것 을 변경할수 없고 멤버 데이터들이 참조하는 값을 변경할 수 있습니다. Const가 아닌 함수 객체는 얕은 복사입니다.)
물론, 만약 람다함수 객체가 참조로 캡쳐된 지역변수들 보다 오래 생존(instantiate) 하게 되면 프로그램은 죽게 됩니다(crashtrocity : 뭔소리야?!!).
또한, 기본 캡쳐를 사용할 수도 있습니다. ; [&] 는 " 참조로 모든 변수를 캡쳐한다”를 의미 합니다.
만약 몇 개는 참조로하고 몇 개는 값으로 캡쳐하고 싶을땐 어떻게 할까요?
[a, b, c, &d, e, &f, g] 방법을 생각하겠지만, 여러분들은 capture-default 를 지정하고 특정 지역변수들에 대해 오버라이드 할 수 있습니다.
아래 예제는 위에 나온 예제capturekittybymutablevalue.cpp 를 수정한 것입니다.:
C:\Temp>type overridekitty.cpp
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
int sum = 0;
int product = 1;
int x = 1;
int y = 1;
for_each(v.begin(), v.end(), [=, &sum, &product](int& r)mutable {
sum += r;
if (r != 0) {
product *= r;
}
const int old = r;
r *= x * y;
x = y;
y = old;
});
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
cout << "sum: " << sum << ", product: " << product << endl;
cout << "x: " << x << ", y: " << y << endl;
}
C:\Temp>cl /EHsc /nologo /W4 overridekitty.cpp && overridekitty
overridekitty.cpp
0 0 0 6 24 60 120 210 336 504
sum: 45, product: 362880
x: 1, y: 1
|
여기서는 x,y를 값으로 캡쳐하고, (람다 내부에서만 수정되어져야 하기 때문) sum, produce는 참조로 캡쳐 했습니다. 반대로 lambda-introducer를 [&, x, y] 로 해도 같은 같은 결과 입니다.
그럼 this 는 어떻게 할 까요?
C:\Temp>type memberkitty.cpp
#include
#include
#include
#include
using namespace std;
class Kitty {
public:
explicit Kitty(int toys) : m_toys(toys) { }
void meow(const vector
for_each(v.begin(), v.end(), [m_toys](int n) {
cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
});
}
private:
int m_toys;
};
int main() {
vector
for (int i = 0; i < 3; ++i) {
v.push_back(i);
}
Kitty k(5);
k.meow(v);
}
C:\Temp>cl /EHsc /nologo /W4 memberkitty.cpp
memberkitty.cpp
memberkitty.cpp(12) : error C3480: 'Kitty::m_toys': a lambda capture variable must be from an enclosing function scope
|
람다 수식 문법은 지역변수를 캡쳐하는건 허용하지만 멤버 변수의 캡쳐는 허용하지 않습니다. 대신 특별히 this 포인터를 캡쳐 할 수 있습니다. :
C:\Temp>type workingmemberkitty.cpp
#include
#include
#include
#include
using namespace std;
class Kitty {
public:
explicit Kitty(int toys) : m_toys(toys) { }
void meow(const vector
for_each(v.begin(), v.end(), [this](int n) {
cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
});
}
private:
int m_toys;
};
int main() {
vector<int> v;
for (int i = 0; i < 3; ++i) {
v.push_back(i);
}
Kitty k(5);
k.meow(v);
}
C:\Temp>cl /EHsc /nologo /W4 workingmemberkitty.cpp > NUL && workingmemberkitty
If you gave me 0 toys, I would have 5 toys total.
If you gave me 1 toys, I would have 6 toys total.
If you gave me 2 toys, I would have 7 toys total.
|
this를 캡쳐하면 m_toys멤버 변수는 암시적으로 this->m_toys를 의미 한다는 것을 생각 할 수 있습니다. (람다 수식 내부에선, this는 캡쳐된 this를의미하지 람다 객체의 this포인터를 의미하지 않습니다. : 람다함수의 this 포인터에는 접근할 수 없습니다.)
this를 암시적으로 캡쳐할 수 있습니다:
C:\Temp>type implicitmemberkitty.cpp
#include
#include
#include
#include
using namespace std;
class Kitty {
public:
explicit Kitty(int toys) : m_toys(toys) { }
void meow(const vector
for_each(v.begin(), v.end(), [=](int n) {
cout << "If you gave me " << n << " toys, I would have " << n + m_toys << " toys total." << endl;
});
}
private:
int m_toys;
};
int main() {
vector
for (int i = 0; i < 3; ++i) {
v.push_back(i);
}
Kitty k(5);
k.meow(v);
}
C:\Temp>cl /EHsc /nologo /W4 implicitmemberkitty.cpp > NUL && implicitmemberkitty
If you gave me 0 toys, I would have 5 toys total.
If you gave me 1 toys, I would have 6 toys total.
If you gave me 2 toys, I would have 7 toys total.
|
[&]로 할수 있지만 , this는 포함 되지 않습니다.(항상 값으로 전달됩니다.) , [&this]는 안됩니다.
람다 소개자(lambda-introducer)에 아무런 값을 넣고 싶지 않으면, lambda-parameter-declaration 전체는 생략 됩니다. :
C:\Temp>type nullarykitty.cpp
#include
#include
#include
#include
#include
using namespace std;
int main() {
vector<int> v;
int i = 0;
generate_n(back_inserter(v), 10, [&] { return i++; });
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
cout << "i: " << i << endl;
}
C:\Temp>cl /EHsc /nologo /W4 nullarykitty.cpp > NUL && nullarykitty
0 1 2 3 4 5 6 7 8 9
i: 10
|
[&]() { return i++; }와 비교해서 2문자( () ) 가 빠져 있습니다 .
lambda-parameter-declaration 을 생략하는 건 여러분들 마음입니다.
장난 삼아 아래의 코드는 C++0x 에서 유효한 코드입니다.:
C:\Temp>type nokitty.cpp
int main() {
[](){}();
[]{}();
}
|
위의 예제는 아무런 동작을 하지 않는 두 개의 람다를 생성합니다.
(첫 번째는 lambda-parameter-declaration이 있고 두 번째는 없습니다.)
추가적으로 사용할 수 있는 lambda-parameter-declaration 은 문법적으로아래와 같이 구성되어있습니다. :
( lambda-parameter-declaration-listopt ) mutableopt exception-specificationopt lambda-return-type-clauseopt
그래서 mutable 이나 ->리턴타입 을 지정하고 싶으면 lambsa-introducer( [] )와 그 사이에 빈 공간이 필요 합니다.
마지막으로, 람다는 보통의 함수 객체를 만들어 내기 때문에 , 함수 객체들을 tr1::function 에 보관 할 수도 있습니다.:
C:\Temp>type tr1kitty.cpp
#include
#include
#include
#include
#include
using namespace std;
using namespace std::tr1;
void meow(const vector
for_each(v.begin(), v.end(), f);
cout << endl;
}
int main() {
vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
}
meow(v, [](int n) { cout << n << " "; });
meow(v, [](int n) { cout << n * n << " "; });
function
meow(v, g);
}
C:\Temp>cl /EHsc /nologo /W4 tr1kitty.cpp > NUL && tr1kitty
0 1 2 3 4 5 6 7 8 9
0 1 4 9 16 25 36 49 64 81
0 1 8 27 64 125 216 343 512 729
|
댓글
댓글 쓰기