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;

 

             // 삐꾸예제 - 동작이 되면 좋겠지만, 원하는 대로 동작하지 않는다.
             for_each( vec.begin(), vec.end(), boost::bind( &Cfoo::print_n, _1, i++ ) );
 
             // boost::bind 를 이용한 예제 - 함수를 만들고 다시 bind 시켜주어야 한다.
             for_each( vec.begin(), vec.end(), boost::bind( &Cfoo::print_n, _1, boost::bind( incrementFunc, i ) ) );

 

             // 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];

             forint 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 };
std::sort( nTest, nTest+5, std::less<int>() );
std::copy( nTest, nTest+5, std::ostream_iterator<int>( std::cout, "." ) );



 

반응형

'메타프로그래밍 > 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

+ Recent posts