스토리텔링 개발자

[Effective STL] 41. ptr_fun, mem_fun, mem_fun_ref(C++98) 본문

개발/Effective STL

[Effective STL] 41. ptr_fun, mem_fun, mem_fun_ref(C++98)

김디트 2025. 1. 9. 11:14
728x90

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

 

 

 

  • 참고 : 현재도 사용할 수 있지만, 람다 등에 의해 이제 사용 빈도가 지극히 낮아졌다.
ptr_fun, mem_fun, mem_fun_ref가 하는 일
  • 우선 함수 호출 문법 종류를 알아보자.
f(x); // 1. 멤버 함수가 아닌 경우
x.f(); // 2. x의 멤버 함수인 경우
xp->f(); // 3. x의 멤버 함수이나, x의 포인터로 호출된 경우
  • 그리고 아래의 코드를 보자.
// case 1
void test(Widget& w); // w를 검사하고, 실패 시 failed를 출력하는 함수
vector<Widget> vw1;
...
for_each(vw1.begin(), vw1.end(), test); // 컴파일 성공
// 이 경우 for_each에서는 함수 호출 문법 1이 사용되어야 한다.

// case 2
class Widget
{
public:
    void test(Widget& w); // w를 검사하고, 실패 시 failed를 출력하는 함수
...
};
vector<Widget> vw2;
...
for_each(vw2.begin(), vw2.end(), &Widget:test); // 컴파일 실패..
// 이 경우 for_each에서는 함수 호출 문법 2가 사용되어야 한다.

// case 3
vector<Widget*> lpw; // 이번엔 포인터를 가진다.
...
for_each(lpw.begin(), lpw.end(), &Widget:test); // 여전히 컴파일 실패..
// 이 경우 for_each에서는 함수 호출 문법 3이 사용되어야 한다.
  • 하지만 for_each의 구현을 보면.. 함수 호출 문법 1 만을 고려하고 있음을 알 수 있다.(물론 C++98 이하 한정)
template(typename InputIterator, typename Function)
Function for_each(InputIterator begin, InputIterator end, Function f)
{
    while(begin != end) f(*begin++); // 함수 호출 문법 1만을 고려한다.
}
  • 이런 경우, 함수 호출 문법1에 대응해주기 위해서 mem_fun과 men_fun_ref 함수가 존재한다.

 

 

 

mem_fun과 mem_fun_ref
  • 이들은 함수를 함수 객체로 래핑해주는 일을 한다.
// 매개변수를 받지 않고, const 멤버가 아닌 멤버 함수에 대한 mem_fun 선언문
// C : 클래스, R : 포인터로 가리켜지는 멤버 함수(pmf)의 반환값 타입
template<typename R, typename C>
mem_fun_t<R, C> mem_fun(R(C::*pmf)()); // pmf를 받아, mem_fun_t 타입 객체를 반환한다.
  • mem_fun
    • 멤버 함수 포인터를 함수 객체로 변환한다.
    • 함수 호출 문법 1을 함수 호출 문법 3으로 바꾸어주는 역할을 한다.
  • mem_fun_ref
    • 멤버 함수 레퍼런스를 함수 객체로 변환한다.
    • 함수 호출 문법 1을 함수 호출 문법 2로 바꾸어주는 역할을 한다.
  • 아래는 mem_fun 사용 예시이다.
list<Widget*> lpw;
...
for_each(lpw.begin(), lpw.end(), mem_fun(&Widget::test); // 이제 컴파일 성공
// for_each는 Widget::test의 포인터를 가지는 mem_fun_t 타입 객체를 받는다.
  1. for_each 내부에서 함수 호출 문법 1을 사용하여 mem_fun_t를 호출한다.
  2. 호출된 mem_fun_t 에서는 함수 호출 문법 3을 사용하여 Widget::test를 호출한다.

 

 

 

숨겨진 역할
  • 이 함수들은 adaptable하게 동작할 수 있도록 하는 typedef들도 지원한다.(항목 40 참조)
  • 물론 모던 C++에서는 의미 없는 사항이지만..

 

 

 

각기 사용해야 할 때?
  • ptr_fun을 사용해야 할 때
    • // 컴파일 성공
      for_each(vw.begin(), vw.end(), test);
      // 여전히 컴파일 성공
      // typedef를 좀 추가한다고 해서 해될 것은 없다.
      for_each(vw.begin(), vw.end(), ptr_fun(test));
    • STL 컴포넌트에 함수를 넘길 때는 항상 사용한다고 생각하면 편하다.
    • STL은 전혀 신경쓰지 않고, 런타임 수행 성능도 저하되지 않는다.
    • 물론 꼭 필요할 때만, 즉 컴파일 에러가 발생할 때만 씌워줘도 무방하다.
  • mem_fun / mem_fun_ref를 사용해야 할 때
    • STL 컴포넌트에 함수를 넘길 때는 반드시 사용해야 한다.
728x90
Comments