엄범


lambda가 왜 필요하냐면,

함수 포인터는 함수이기 때문에 상태를 가질 수 없다.

반복문 같은데 인자로 함수를 넘겨야 하는 상황에서 그 함수가 상태를 가져야 하는 경우, 함수 포인터를 사용할 수 없다.

따라서 상태를 가지는 함수를 만들기 위해서 함수 객체라는 트릭을 사용해야 했다.

함수 객체는 객체인데, ``cpp operator()``를 오버로드해서 함수처럼 호출할 수 있는 객체를 의미한다. 

Function object는 보통 Functor라고 부른다.

```cpp

struct Functor {

     void operator()() {

          std::cout << "Functor" << std::endl;

     }

};

``` 

이렇게 별도의 Functor를 정의해주는 것이 번거롭고 지저분하다. 


그래서 상태를 가지는 함수를 표현하기 위해 lambda를 사용한다.

```cpp

[captures](parameters) { body }

// mutable, exception, trailing-return-type 지정도 가능하나 선택 사항이다.

```

캡쳐할 변수를 `` []``에 지정하면 된다. 기본은 값 캡쳐이며 ``c &var``를 지정하면 참조 캡쳐다.

캡쳐할 변수를 명시적으로 지정하지 않아도, 바디에서 쓰이는 변수가 자동으로 캡쳐되도록 할 수 있다.

  • ``c [&]`` 바디에서 쓰이는 모든 변수, 상수를 참조로 캡쳐하고 현재 객체 참조 캡쳐.
  • ``c [=]`` 바디에서 쓰이는 모든 변수, 상수를 값으로 캡쳐하고 현재 객체 참조 캡쳐.
  • ``c []`` 아무것도 캡처하지 않음.
  • ``c [this]`` 현재 객체 참조 캡쳐

* 참고. ``cpp std::bind()``에서 참조 캡쳐(?)처럼 사용하려면 ``cpp cref(variable)``를 사용한다. 보통 bind 보다는 그냥 람다 쓰는게 좋다.


다음과 같이 람다 내부에서 외부에 있는 변수의 값을 수정할 수 있다.

```cpp

int i = 0;

auto f = [&i](std::string name) {std::cout << ++i << name << '\n';  };

f("umbum");

std::cout << i << '\n';

```

```

1umbum

1

```


그런데, 람다 내부에서 외부에 있는 변수를 참조가 아니라 값으로 받아와 수정하고 싶다면 ``cpp mutable``을 붙여주어야 한다.

```cpp

int i = 0;

auto f = [i](std::string name) mutable {std::cout << ++i << name << '\n';  };

f("umbum");

std::cout << i << '\n';

```

```

1umbum

0

```


``cpp this``를 넣으면 현재 객체를 참조 캡쳐할 수 있다. 

lambda는 friend 함수로, ``cpp private``로 지정된 멤버에도 접근 가능하다.

```cpp

[this]() { std::cout << "cls name : " << name << std::endl; }();

```


bind와 bind1st는 호환이 되긴 된다.

```cpp
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
void bind_test() {
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int N = sizeof(x) / sizeof(int);

typedef std::_Binder<std::_Unforced, std::multiplies<int>, int, const std::_Ph<1> & > Function;
typedef boost::transform_iterator<Function, int*> doubling_iterator;

using namespace std::placeholders;
auto bind_f = std::bind(std::multiplies<int>(), 2, _1);
doubling_iterator i(x, bind_f);
doubling_iterator i_end(x + N, bind_f);

std::cout << "multiplying the array by 2:" << std::endl;
while (i != i_end)
std::cout << *i++ << " ";
std::cout << std::endl;
}
```
```cpp
void bind1st_test() {
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int N = sizeof(x) / sizeof(int);

typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator<Function, int*> doubling_iterator;

auto bind1st_f = std::bind1st(std::multiplies<int>(), 2);
doubling_iterator i(x, bind1st_f);
doubling_iterator i_end(x + N, bind1st_f);

std::cout << "multiplying the array by 2:" << std::endl;
while (i != i_end)
std::cout << *i++ << " ";
std::cout << std::endl;
}
```

근데 ``cpp bind1st(), binder1st`` 같은 경우 C++11에서 deprecated 되었고, 

그냥 ``cpp bind()``는 람다의 한계(템플릿으로 여러 타입 받기, move capture)로 아직까지는 사용하나 이런 케이스가 아니라면 그냥 람다를 사용하는 편이 좋다.


```cpp

void lambda_test() {

int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };

const int N = sizeof(x) / sizeof(int);


typedef boost::transform_iterator<std::function<int(int)>, int*> doubling_iterator;

std::function<int(int)> doubling_lambda = [](int x) { return x * 2; };  // or just auto.

doubling_iterator i(x, doubling_lambda);

doubling_iterator i_end(x + N, doubling_lambda);


std::cout << "multiplying the array by 2:" << std::endl;

while (i != i_end)

std::cout << *i++ << " ";

std::cout << std::endl;

}

```