http://cafe.naver.com/ecpp/9
멤버함수의 포인터 형 타입선언과 포인터변수 선언과 그 간단한 사용 예를 올립니다.
대략 모양새는 알고 있지만 쓸데 마다 헷갈리더군요. 아래의 코드 사용 예 정도만 외워둔다면 멤버함수포인터에서는 별로 어려움이 없으리라 봅니다.
#include <iostream>
using namespace std;
//----------------------------------------------------------------
class Cfoo { public: Cfoo() : doit_count(0), domore_count(0) {}
int DoIt( float a, char b, char c ) { cout << "DoIt-" << a << b << c << endl; return doit_count++; } int DoMore( float a, char b, char c ) { cout << "DoMore-" << a << b << c << endl; return domore_count++; }
private: int doit_count; int domore_count; };
//----------------------------------------------------------------
void main() { typedef int (Cfoo::*pt2Member)(float, char, char);
pt2Member funcArr1[10] = {NULL};
int (Cfoo::*funcArr2[10])(float, char, char) = {NULL};
funcArr1[0] = funcArr2[1] = &Cfoo::DoIt; funcArr1[1] = funcArr2[0] = &Cfoo::DoMore;
Cfoo instance; cout << (instance.*funcArr1[0])(1, 'a', 'b') << endl; cout << (instance.*funcArr1[1])(2, 'a', 'b') << endl;
// cout << (instance.*funcArr1[2])(3, 'a', 'b') << endl; - Runtime Error!
cout << (instance.*funcArr2[1])(34, 'a', 'b') << endl; cout << (instance.*funcArr2[0])(89, 'a', 'b') << endl; }
그럼 std::mem_fun 과 std::mem_fun_ref 그리고 boost::mem_fn 에 대해 알아보자.
mem_fun 은 객체포인터에 적용가능하고, mem_fun_ref 는 객체에 적용된다. 아래 예제를 작성하면서도 상당히 헷갈려서 컴파일에러 땜시 많은 고생을 하였다. ㅡㅡ;;
boost::mem_fn 은 이런 구분이 없이 사용 가능하다. 역시 boost 가 좋다!
mem_fun1 이란 것도 있는데 이 또한 bind1st, bind2nd 와 같이 역시 파라메타의 개수에 제한을 받게 된다.
역시 boost 는 이런 제한과 구분 없이 하나를 사용하여 다 적용이 가능하다.
#include <vector> #include <iostream> #include <functional> #include <algorithm> #include <boost/bind.hpp> #include <boost/mem_fn.hpp>
class Cfoo { public: Cfoo( ) : count(0) {} Cfoo( int n ) : count(n) {} void print() { std::cout << "print - " << count++ << std::endl; } void print_n( int n ) { std::cout << "print_n - " << count++ << std::endl; } private: int count; };
const static TEST_COUNT = 3;
int incrementFunc( int& n ) { return n++; }
void main() { using std::for_each;
std::vector<Cfoo> vec; std::fill_n( std::back_inserter(vec), 5, Cfoo(1) );
for_each( vec.begin(), vec.end(), std::mem_fun_ref( &Cfoo::print ) ); for_each( vec.begin(), vec.end(), boost::mem_fn( &Cfoo::print ) );
//------------------------------------------------------------------------------------------- // 함수인자값을 전달하려면, bind 를 이용하라. //-------------------------------------------------------------------------------------------
// 넘 복잡다. for_each( vec.begin(), vec.end(), std::bind2nd( std::mem_fun1_ref<void, Cfoo, int>( &Cfoo::print_n ), 111) );
// 오, 템플릿인자들이 생략가능하다. for_each( vec.begin(), vec.end(), std::bind2nd( std::mem_fun1_ref( &Cfoo::print_n ), 222) );
// boost 형식으로 바꾸면 아래와 같이 되기도 합니다. for_each( vec.begin(), vec.end(), boost::bind( boost::mem_fn( &Cfoo::print_n ), _1, 222) );
// 간단히 바꿀수 있다. 역시 boost 가 좋다. for_each( vec.begin(), vec.end(), boost::bind( &Cfoo::print_n, _1, 333 ) );
//------------------------------------------------------------------------------------------- // bind 를 할때 함수인자를 가변값으로 줄 수 있는 방법 ( boost::bind 의 한계 )
int i = 0;
// 삐꾸예제 - 동작이 되면 좋겠지만, 원하는 대로 동작하지 않는다.
// boost::lambda 를 이용한 예제 - boost::lambda 를 이용하면 한 문장으로 가능하다. 가장 진화된 형태 for_each( vec.begin(), vec.end(), boost::lambda::bind( &Cfoo::print_n, boost::lambda::_1, boost::lambda::var( i )++ ) );
//------------------------------------------------------------------------ // 아래와 같이 배열의 포인터도 알고리즘에 바로 적용가능하다. //------------------------------------------------------------------------
Cfoo foo_[TEST_COUNT]; for_each( foo_, foo_+TEST_COUNT, std::mem_fun_ref( &Cfoo::print ) ); for_each( foo_, foo_+TEST_COUNT, boost::mem_fn( &Cfoo::print ) );
Cfoo* pfoo[TEST_COUNT]; for( int i=0; i<TEST_COUNT; ++i ) { pfoo[i] = &foo_[i]; } for_each( pfoo, pfoo+TEST_COUNT, std::mem_fun( &Cfoo::print ) ); for_each( pfoo, pfoo+TEST_COUNT, boost::mem_fn( &Cfoo::print ) );
for_each( pfoo, pfoo+TEST_COUNT, std::bind2nd( std::mem_fun1( &Cfoo::print_n ), 100 ) );
// 위의 코드를 boost 로 바꾸면... for_each( pfoo, pfoo+TEST_COUNT, boost::bind( boost::mem_fn( &Cfoo::print_n ), _1, 100 ) ); for_each( pfoo, pfoo+TEST_COUNT, boost::bind( &Cfoo::print_n, _1, 222 ) ); }
-----------------------------------------------------------------------------------------------------------------------------
위의 예제에서 배열을 알고리즘에서 적용하였는데요.
이는 포인터가 반복자중에 하나인 입력반복자의 필요충분조건을 모두 만족하다는 것입니다.
입력반복자가 되기 위한 조건은 아래와 같다.
1. 연산자 후방++, 전방++ 가 적용가능하고, 다음 입력반복자를 리턴해준다. 2. 연산자 !=, == 가 적용가능하고, 적절히 true, false 를 리턴해준다. 3. 연산자 * 가 적용가능하고, *it 는 it 가 가리키는 값을 리턴해준다. 4. 연산자 +,- 가 적용가능하고, 해당 입력반복자를 리턴해준다.
입력반복자는 한가지타입을 지칭하는 것이 아니라 위의 3가지 조건을 모두 만족하기만 하면, 그러한 타입을 입력반복자라고 한다.
아래의 예는 배열의 원소들을 sort 시키는 방법을 보여준다.
int nTest[5] = { 7, 10, 6, 1, 3 }; |
'메타프로그래밍 > Boost::' 카테고리의 다른 글
boost::function (0) | 2012.11.13 |
---|---|
boost::unordered_set (0) | 2012.11.13 |
boost::bind (0) | 2012.11.13 |
boost::mem_fn (0) | 2012.11.13 |
boost::unordered_map (0) | 2012.11.13 |