내가 STL에 조예가 깊어서 글을 남기는 것이 아니라, Effecitve STL 을 공부하는 사람들이 이 글을 보고,
도움이 되었으면 하는 생각과, 혹시 내가 틀린것이 있다면 지적해 주시지 않을까 란 생각으로 글을 올리는것임을 미리 밝힙니다. - 최익필
이번 항목은 한참 해맷다. 4시간 정도.. 화딱지 나는 항목이였다. 객체지향 프로그램밍으로 코드를 짜다보면 함수를 함수 객체로 만들어야 할 때가 있다. 이런 함수 객체를 다시 다른 함수객체를 만들기 위해선 코드를 다시 짜야 하는데, 이 과정이 무척 귀찮다. 그래서인지 STL에선 다른 형태로 함수 객체를 변경하는 어댑터를 제공한다.
어떠한가? 흥미롭지 아니한가? 그렇기 때문에, 함수 객체를 만들고자 한다면, 어댑터 적용이 가능하게끔~ 하자는 이야기가 이번 항목이다.
이 어댑터가 적용되게 하려면, 한가지 규칙을 따라야 한다. 바로 어댑터가 사용하는 typedef 를 정의해 두어야 한다는것 이다. 어댑터가 사용하는 typedef는 argument_type, first_argument_type, second_argument_type, result_type 4개이다.
왜 이것 때문에 4시간동안 해맸는가?
p.256의 예제코드로 컴파일을 하여도 컴파일이 되지 않았기 때문이다. predicate class 정의 시 operator 는 매개변수를 레퍼런스로 받는 시그네처를 가진 구조였다. ptr_fun 은 잘되었지만 ptr_fun 으로 반환된 함수 객체를 not1 는 받아 들이지 못했다. 그래서 다 타고 들어가서 시그네처를 확인했다.
그게 4시간이나 걸렸다. .. 컴파일 에러만 잘 조사했더라면 금방 끝났을 텐데, 문제의 원인은 ptr_fun 을 만들면서 argument_type 이 레퍼런스로 정의되어지고(템플릿으로 컴파일 타임에 인스턴스화 된다.) not1 에서의 operator() 가 레퍼런스로 받는 구조가 되면서 레퍼런스의 레퍼런스를 인자로 받게 된다.
확인 코드
보면 알겠지만 ptr_fun 으로 만들어진 함수 객체의 argument_type 을 받아 들이고, not1 으로 만들어진 함수 객체는 bool operator( const typename _Fn1::argument_type& _Left ) 로 정의되면서 (argument_type&)& 가 되어진다. .. std 를 변경할수 없으니 .. 함수 매개자를 값에 의한 복사로 처리하여 해결하였다. (포인터가 더 효과적이거나 piml 구조로 클래스를 만드는 습관을 길러야 할듯)
이번 항목은 한참 해맷다. 4시간 정도.. 화딱지 나는 항목이였다. 객체지향 프로그램밍으로 코드를 짜다보면 함수를 함수 객체로 만들어야 할 때가 있다. 이런 함수 객체를 다시 다른 함수객체를 만들기 위해선 코드를 다시 짜야 하는데, 이 과정이 무척 귀찮다. 그래서인지 STL에선 다른 형태로 함수 객체를 변경하는 어댑터를 제공한다.
어떠한가? 흥미롭지 아니한가? 그렇기 때문에, 함수 객체를 만들고자 한다면, 어댑터 적용이 가능하게끔~ 하자는 이야기가 이번 항목이다.
이 어댑터가 적용되게 하려면, 한가지 규칙을 따라야 한다. 바로 어댑터가 사용하는 typedef 를 정의해 두어야 한다는것 이다. 어댑터가 사용하는 typedef는 argument_type, first_argument_type, second_argument_type, result_type 4개이다.
이런 추가 작업이 좀 귀찮았는지 STL에선 STL에선 typedef가 정의된 템플릿(template struct unarry_function, bainary_function 이 std 에 정의되어 있다.) 구조체(클래스여도 상관없다. 개인취향)를 제공하고 있으며, 이것을 상속하면 손 쉽게 정의 가능해 진다.
어댑터 만들때의 헬퍼
아래 코드는 형태 변환할 때의 요구 사항
왜 이것 때문에 4시간동안 해맸는가?
p.256의 예제코드로 컴파일을 하여도 컴파일이 되지 않았기 때문이다. predicate class 정의 시 operator 는 매개변수를 레퍼런스로 받는 시그네처를 가진 구조였다. ptr_fun 은 잘되었지만 ptr_fun 으로 반환된 함수 객체를 not1 는 받아 들이지 못했다. 그래서 다 타고 들어가서 시그네처를 확인했다.
그게 4시간이나 걸렸다. .. 컴파일 에러만 잘 조사했더라면 금방 끝났을 텐데, 문제의 원인은 ptr_fun 을 만들면서 argument_type 이 레퍼런스로 정의되어지고(템플릿으로 컴파일 타임에 인스턴스화 된다.) not1 에서의 operator() 가 레퍼런스로 받는 구조가 되면서 레퍼런스의 레퍼런스를 인자로 받게 된다.
확인 코드
보면 알겠지만 ptr_fun 으로 만들어진 함수 객체의 argument_type 을 받아 들이고, not1 으로 만들어진 함수 객체는 bool operator( const typename _Fn1::argument_type& _Left ) 로 정의되면서 (argument_type&)& 가 되어진다. .. std 를 변경할수 없으니 .. 함수 매개자를 값에 의한 복사로 처리하여 해결하였다. (포인터가 더 효과적이거나 piml 구조로 클래스를 만드는 습관을 길러야 할듯)
자세한 기본 내용은
"C++ Standard Library 레퍼런스 튜토리얼" 책을 보면 매우 자세하게 나와 있다.
2009년 4월 16일
이제는 이런 고민자체를 하지 않는다. 왜냐하면 boost::bind를 사용하기 때문이다. ...
'책 정리 > Effective STL' 카테고리의 다른 글
항목 45 : count, find, binary_search, lower_bound, upper_bound, 그리고 equal_range 를 제대로 파악해 두자. (0) | 2008.09.07 |
---|---|
항목 44 : 같은 이름을 가진 것이 있다면 일반 알고리즘 함수보다 멤버 함수가 더 낫다. (0) | 2008.09.07 |
항목 43 : 어설프게 손으로 작성한 루프보다는 알고리즘이 더 낫다. (0) | 2008.09.07 |
항목 42 : less<T>는 operator<의 의미임을 꼭 알아두자. (0) | 2008.09.07 |
항목 41 : ptr_fun, mem_fun, mem_fun_ref의 존재에는 분명한 이유가 있다. (0) | 2008.09.07 |
항목 39 : 술어 구문은 순수 함수로 만들자. (0) | 2008.09.05 |
항목 38 : 함수자 클래스는 값으로 전달되도록(pass-by-value) 설계하자. (0) | 2008.09.05 |
항목 37 : 범위 내의 데이터 값을 요약하거나 더하는 데에는 accumilate나 for_each를 사용하자 (1) | 2008.09.05 |
항목 36 : copy_if를 적절히 구현해 사용하자 (0) | 2008.09.03 |
항목 35 : 대소문자를 구분하지 않는 문자열 비교는 mismatch 아니면 lexicographical_compare를 써서 간단히 구현할 수 있다. (0) | 2008.09.03 |
최근댓글