방프리
Effective STL 이해하지 못한 항목 - 4 본문
항목 41. ptr_fun, mem_fun, mem_fun_ref의 존재에는 분명한 이유가 있다.
위의 함수들이 C++이 원래부터 가진 문법적 모순을 감싸주는 함수라고 합니다. (몰라요 전.... 저자가 그랬어요...)
무슨 모순인지 예제를 통해서 알아보겠습니다.
f란 이름의 함수와 x란 이름의 객체가 있습니다.
x에 대해 f를 호출하고 싶으며, 호출하는 위치는 x의 멤버 함수의 바깥쪽입니다.
이런 상황에서 다음과 같은 문법을 제공할 수 있습니다.
f(x); // 문법 #1 : f가 멤버 함수가 아닌 경우
x.f(); // 문법 #2 : f가 x의 멤버 함수이고, x는 객체이든지 객체에 대한 참조자인 경우
p->f(); // 문법 #3 : f가 x의 멤버 함수이고, p는 x 객체에 대한 포인터인 경우
void test(Widget& w); // w를 검사해서 실패 시 failed라고 표시
vector<Widget> vw;
for_each(vw.begin(), vw.end(), test); //#호출1. OK
만약 test가 보통 함수가 아닌 Widget의 멤버함수 일 경우, 즉, Widget에서 자체 검사할 경우
class Widget
{
public :
void test();
}
for_each(vw.begin(), vw.end(), &Widget::test); //호출#2. ERROR
list<Widget*> lpw; //widget에 대한 포인터의 경우
for_each( lpw.begin(), lpw.end(), &Widget::test ); //호출#3. ERROR
template<typedef InputIterator, typename Function>
Function for_each( InputIterator begin, INputIterator end, Function f)
{
while(begin != end )
f(*begin++);
}
위의 코드에서 for_each 호출을 보면 문법 #1이 맞습니다.
즉, 함수와 함수 객체는 항상 '비멤버 함수'에 대한 문법 형태를 통해 호출되어야 합니다.
그러므로 문법#2와 문법#3는 실행되지 않습니다.
template<typename R, typename C>
mem_fun_t<R, C>
mem_fun< R(C::*pmf)() );
여기서 mem_fun, mem_fun_ref는 함수 템플릿입니다.
mem_fun은 멤버 함수의 포인터 pmf를 받아 mem_fun_t 타입의 객체를 반환합니다.
즉 멤버 함수 포인터를 가지고 있으면서 operator()에 넘겨진 객체에 대해 멤버 함수를 호출 해주는
함수자 클래스 입니다.
list<Widget*> lpw;
for_each( lpw.begin(), lpw.end(), mem_fun( &Widget::test)); //OK
for_each는 Widget::test의 포인터를 가지고 있는 mem_fun_t 타입의 객체를 받습니다.
for_each는 lpw 내의 Widget*에 대해 mem_fun_t 객체를 불러옵니다.
이 때 문법 #1사용되며, mem_fun_t 객체는 바로 Widget*에 대해 Widget::test를 호출합니다.
for_each(vw.begin(), vw.end(), ptr_fun(test) ); //호출#1 OK
// test에 ptr_fun을 사용할 필요는 없지만 추가되어도 전혀 해가 없습니다.
// STL 컴포넌트에 함수를 넘길 때 사용해도 되며, 성능 저하도 없습니다.
mem_fun과 mem_fun_ref에 대해 정리하자면
1. 함수 객체 생성 시 템플릿 인자로 멤버 함수의 클래스명을 기억하고 있다가 멤버 함수로써의 포인터를
함수 객체가 저장할 수 있게 됩니다.
2. 그리고 operator()의 매개변수를 컨테이너의 객체로 받고, 이 객체를 타고 들어가,
함수 객체가 가지고 있던 포인터를 결합하여 호출 할 수 있게 됩니다.
3. 이 때 컨테이너 객체가 * 로 저장되어 있다면 mem_fun을 사용하면 되고,
객체 자체로 저장되어 있거나 &로써 저장되어 있다면 mem_fun_ref를 호출하면 됩니다.
'C++ > EffectiveSTL' 카테고리의 다른 글
Effective STL 이해하지 못한 항목 - 3 (0) | 2020.01.19 |
---|---|
Effective STL 이해하지 못한 항목 - 2 (0) | 2020.01.19 |
Effective STL 이해하지 못한 항목 - 1 (0) | 2020.01.18 |
Effective STL (0) | 2020.01.18 |