일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 참조자
- c++
- exception
- implicit conversion
- 영화
- lua
- 티스토리챌린지
- 스마트 포인터
- reference
- Vector
- Effective c++
- 암시적 변환
- 오블완
- more effective c++
- 예외
- effective stl
- 반복자
- virtual function
- 비교 함수 객체
- 다형성
- 메타테이블
- 영화 리뷰
- 언리얼
- resource management class
- 상속
- UE4
- 루아
- Smart Pointer
- operator new
- 게임
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 41. ptr_fun, mem_fun, mem_fun_ref(C++98) 본문
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 타입 객체를 받는다.
- for_each 내부에서 함수 호출 문법 1을 사용하여 mem_fun_t를 호출한다.
- 호출된 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
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 43. 루프보단 알고리즘 (0) | 2025.01.13 |
---|---|
[Effective STL] 42. less<T> (0) | 2025.01.10 |
[Effective STL] 40. adaptable한 함수 객체(C++98) (0) | 2025.01.08 |
[Effective STL] 39. predicate는 순수 함수일 것 (0) | 2025.01.07 |
[Effective STL] 38. 함수 객체 클래스 값 전달(pass by value) 고려하기 (0) | 2025.01.03 |
Comments