많은 STL 알고리즘들이 펑크터(Functor)라고 부르는 함수 객체를 사용한다. 펑크터는 함수처럼 ()와 함께 쓸 수 있는 객체다. 일반 함수의 이름, 함수를 지시하는 포인터, () 연산자 오버로딩된 클래스 객체(operator()), 즉 ()가 붙은 해괴망측한 것들은 다 펑크터가 될 수 있다. 예를 들어보자.
class Linear
{
private:
double slope;
double y0;
public:
Linear(double _s1 = 1, double _y = 0)
: slope(_s1), y0(_y) { }
double operator()(double x) {return y0 + slope * x;}
};
여기서 오버로딩된 () 연산자는 다음과 같이 사용한다.
Linear f1;
double y1 = f1(12.5); // f1.opeartor(12.5)와 같다.
이전에 for_each를 기억하는가?
for_each(books.begin(), books.end(), ShowReview);
마지막 변수는 함수인데 ()가 빠져있다. 일반적으로 STL 함수의 제3 매개변수는 펑크터일 가능성이 높다. 근데 저건 데이터형을 어떤 식으로 적어야 할까?
for_each의 원형은 다음과 같다.
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
ShowReview()의 원형은 다음과 같다.
void ShowReview(const Review &);
그러면 Function의 데이터형이 void (const Review &)가 되는 것이다. 반환형과 매개변수를 둘 다 받는다. for_each의 반환형도 Function이니 이는 말이 된다. 왜? 저 함수 자체가 제1 매개변수, 제2 매개변수 범위 내에서 제3 매개변수를 실행하는 것이기 때문이다. 즉 제1,2 매개변수는 범위 역할만 하기 때문이다.
펑크터는 몇 가지의 개념을 가진다.
-제너레이터(generator) : 매개변수 없이 호출하는 함수.
-단항 함수(unary function) : 한 개의 매개변수로 호출하는 함수.
-이항 함수(binary function) : 두 개의 매개변수로 호출하는 함수.
-bool 값을 리턴하는 단항 함수는 조건(predicate)이다.
-bool 값을 리턴하는 이항 함수는 이항 조건(binary predicate)이다.
예시로 list 템플릿은 하나의 조건을 매개변수로 받아들이는 remove_if() 멤버를 사용한다. 지정된 범위 내에 조건이 참인 원소들은 삭제하는 멤버다. 그럼 뭐 이렇게 사용한다.
bool TooBig(int n) { return n > 100;} // 조건.
list<int> scores;
...
scores.remove_if(TooBig);
이 코드가 하는 일에 비해, 코드는 굉장히 간결해보인다. 이게 바로 펑크터..?