ptr_fun, mem_fun, mem_fun_ref 의 존재에는 분명한 이유가 있다.

컨테이너에 for_each 를 적용시키는 상황을 생각해보자.

void test(Widget& w);    // Widget에 대해 적용되는 전역함수

vector<Widget> vw; // Widget 컨테이너

for_each(vw.begin(), vw.end(), test);
함수객체로 실행하지 않는 경우 위와 같은 형태의 코드가 만들어 질것이다. 간단하게 생각해 볼때 for_each는
template<typename InputIterator, typename Function>
Function for_each(InputIterator begin, InputIterator end, Function f)
{
while( begin != end ) f(*begin++);
}
와 같은 형태로 수행된다. 즉 전역함수 test를 넘긴것이나 함수객체의 operator()를 오버라이드 해서 넘기는 형태인 function(item) 의 수행을 한다. 물론 당연해 보이는 구현이고 당연한 소리같다.
하지만 for_each를 사용해서 함수를 적용시킬때 전역함수나 함수객체가 아닌 클래스의 맴버함수를 적용시키고 싶다면 어떻게 해야 할까?
이때 사용할수 있는 것이 mem_fun_ref라는 함수 어뎁터이다.
// Widget 에 test라는 맴버함수가 있다고 하자
// for_each로 컨테이너의 모든 항목에 test를 적용하고 싶다.
list<Widget> lw;

for_each(lw.begin(), lw.end(), mem_fun_ref(&Widget::test) );
위와 같은 코드를 쓸수 있다. 즉 mem_fun_ref는 x.test() 로 호출되는 함수 형태를 test(x)로 호출가능한 형태로 바꿔주는 역할을 하는 것이다.(자세한 내용은 책참조..)
그렇다면 x->test() 는?? 즉 컨테이너가 객체의 포인터를 가지고 있는데 맴버함수를 적용시키고 싶다면 어떻게 해야 할까? 이럴때 쓰는것이 mem_fun 어뎁터이다.
// Widget 에 test라는 맴버함수가 있다고 하자
// for_each로 컨테이너의 모든 항목에 test를 적용하고 싶다.
list<Widget*> lpw;

for_each(lpw.begin(), lpw.end(), mem_fun(&Widget::test) );

ptr_fun의 경우는 EffectiveSTL40에도 언급되었는데 언제쓰고 언제쓰는지 헷갈린다면 함수객체가 아닌 함수포인터를 넘길경우는 모두 사용한다고 생각하면 편하다.

추가로 mem_fun 과 mem_fun_ref 의 어뎁터 이름이 이해하기 힘들게 정해진 이유는 책참조.

정리하자면









  • f(x) 형태의 함수 f를 컨테이너 전체등 STL 컴포넌트에서 사용할경우
    -> 그냥 사용하거나 ptr_fun(f) 로 넘길것

  • x.f() 형태인 맴버함수를 컨테이너 전체등 STL 컴포넌트에서 사용할경우
    -> mem_fun_ref(&CALSS::f) 로 넘길것

  • x->f() 형태로 호출될 포인터의 컨테이너에 적용될 맴버함수를 컨테이너 전체등 STL 컴포넌트에서 사용할경우
    -> mem_fun(&CLASS::f) 로 넘길것

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다