더북(TheBook)

1.8.2.2 람다 표현식을 함수에 전달하기

일반적으로 람다 표현식의 타입은 알 수 없다. 제네릭 "람다 표현식 타입"도 없다. 일반적으로 람다 표현식은 다른 함수에 함수를 인수로 전달할 때 사용한다고 설명해왔는데, 그렇다면 인수가 람다 표현식이어야 할 때 매개변수 타입은 어떻게 지정할까 라는 의문이 떠오를 것이다. 여기에는 하나 이상의 방법이 있다. 간단하게 대답하자면 타입 매개변수가 람다 표현식 타입이어야 하는 곳에 함수를 위한 템플릿을 정의하는 것이다. 컴파일러는 항상 람다 표현식의 타입을 알고 있으므로 인수로 주어진 람다 표현식을 받는 매개변수가 있는 함수 템플릿을 인스턴스화할 수 있다. 예제로 살펴보는 게 이해하기 쉬울 것이다. 컨테이너에 저장된 double 값들이 있고, 이 값들을 원하는 대로 바꾸고 싶다고 하자. 예를 들어 이 값을 제곱이나 제곱근으로 바꾼다거나 값이 특정 범위에 있는지에 따라 좀 더 다양하게 값을 바꾸고 싶다. 이럴 때 원소들을 변환하는 부분을 람다 표현식으로 지정할 수 있는 템플릿을 정의할 수 있다. 템플릿은 다음과 같이 정의할 수 있다.

template <typename ForwardIter, typename F>
void change(ForwardIter first, ForwardIter last, F fun)
{
  for(auto iter = first; iter != last; ++iter) // 범위에 있는 각 원소에 대해...
    *iter = fun(*iter); // ... 함수를 객체에 적용한다
}
 

fun 매개변수에는 람다 표현식을 쓸 수 있고, 함수 객체나 일반적인 함수 포인터도 쓸 수 있다. fun이 무엇을 하는지 전혀 모르는데 컴파일러가 이 템플릿을 어떻게 다룰 수 있는지 궁금할 것이다. 컴파일러가 템플릿을 다루지 않는다가 정답이다. 템플릿의 인스턴스화가 필요할 때까지 컴파일러는 템플릿을 어떤 식으로도 처리하지 않는다. 위 템플릿의 경우 람다 표현식에 대한 모든 정보는 템플릿을 사용할 때 컴파일러가 알 수 있다. 위 템플릿의 경우 템플릿을 실제로 쓰는 순간 람다 표현식에 관한 모든 정보를 컴파일러가 이용할 수 있게 된다. 템플릿을 사용하는 예제를 보자.

int data[] {1, 2, 3, 4};
change(std::begin(data), std::end(data), [] (int value){ return value*value; });
 
신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.