[boost]boost.bind - 파트 1
Posted 2009/02/02 10:56|
|
|
댓글 하나가 운영자에겐 커다란 힘이 됩니다!
어디에 쓰이는고 하면, 컨테이너의 객체들을 들 쑤시고 싶을 때, 함수 객체를 사용해야 할 때, 일일이 함수 객체를 만들어 주기 귀찮을 때, 주로 사용 된다.
bind 는 std::bindlst 와 std::bind2nd를 보다 일반화 시킨 함수이다.. bind 는 임의의 함수, 함수 포인터, 함수 객체, 멤버 함수를 함수 객체로 만들 수 있으며, 원하는 위치에 원하는 값을 전달 시킬 수 있는 함수 객체를 만들어 준다. (요구 조건 또한 없다. 묶고 싶다면 bind 라고 외워도 될 정도..)
바인드의 가장 기초가 되는 사용법을 알아보면
view plaincopy to clipboardprint?
- #include <boost/bind.hpp>
- using boost::bind;
- int f(int a, int b)
- {
- return a + b;
- }
- int g(int a, int b, int c)
- {
- return a + b + c;
- }
- int main()
- {
- bind( f, 1, 2 ) ; // == f( 1, 2)
- bind( g, 1, 2, 3 ); // == g( 1, 2, 3 )
- }
여기서 첫번째 바인드 함수 호출 시, 리턴값은 f(1,2) 처럼 행동하는 함수 객체를 리턴하며, 두번째 bind 함수 호출시 g( 1, 2, 3 ) 처럼 행동하는 함수 객체를 리턴 한다. 여기서 1,2,3 은 g의 매개변수의 자리와 상응 되는 자리에 들어 가게 된다. 그러니까 고정된 f(1,2) 또는 g(1,2,3 ) 을 수행 하는 함수 객체를 만들어 리턴시켜 준다.
이 기능만으론 bind 라 할 수 없을 것이다.
다음 소스 코드를 보자.
- #include <boost/bind.hpp>
- using boost::bind;
- int f(int a, int b)
- {
- return a + b;
- }
- int g(int a, int b, int c)
- {
- return a + b + c;
- }
- int main()
- {
- bind( f, 1, 2 ) ; // == f( 1, 2)
- bind( g, 1, 2, 3 ); // == g( 1, 2, 3 )
- int x = 3;
- int y = 4;
- int z = 5;
- bind(f, _2, _1)(x, y); // f(y, x)
- bind(g, _1, 9, _1)(x); // g(x, 9, x)
- bind(g, _3, _3, _3)(x, y, z); // g(z, z, z)
- bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)
- }
이 코드의 24, 25, 26, 27 라인을 보면, 어떻게 사용 하는지 감이 올 것이다. 각 상응 되는 자리에 변수를 지정 해서 대입 할 수 있다는 것을 보여 준다.
그렇다면 _2 와 _1 은 무슨 것일까? _N 는 전달 되는 인수 목록의 N 번째 자리의 인수를 _N 이 써진 곳에 대입 하겠다는 것을 의미한다. 이것은 내가 원하는 형태로 함수의 매개변수 순서를 변경 할 수 있다는 것을 뜻한다.( 만약 요구 되는 함수의 매개변수 순서를 바꾸어야만 한다면, 이렇게 바꾸어서 쓸 수 있따는 것을 의미한다. )
그러므로 bind(f, _2, _1)(x,y) 는 f( y, x ) 가 되는 것이다. .. 정말 환상적이지 않는가?
마지막으로 27라인의 bind(g, _1, _1, _1)(x, y, z); 의 bind 리턴은 g( x, x, x ) 처럼 만들어, 3개의 인수를 받는 함수를 1개의 인수를 받는 함수객체로 변경 할 수 있다는 것을 의미한다.(나머지 인자는 무시 된다) .. 정말 환상적이다.
bind의 의미를 다시 해석하기 위한 코드
- #include <boost/bind.hpp>
- #include <iostream>
- using boost::bind;
- int f(int a, int b)
- {
- return a + b;
- }
- int main()
- {
- int i = 5;
- int x = 3;
- // 사용법 1
- // f의 1번째 매개변수에 i를, 2번째 매개변수에 x를 대입된 결과를 리턴
- std::cout << bind(f, i, _1)(x);
- // 사용법 2
- // f의 1번째 매개변수에 i를, 2번째 매개변수에 x를 대입된 함수 객체를 리턴
- bind(f, i, x );
- // 사용법 3
- // f의 1번째 매개변수에 1을, 2번째 매개변수에 i를 대입된 함수 객체를 리턴
- bind(f, 1, i );
- // 사용법 4
- // f의 1번째 매개변수에 x를, 2번째 매개변수에 x를 대입된 결과를 리턴
- std::cout << bind(f, _1, x )( x );
- }
주석을 달아 두었다. 한가지 다시 짚어 본다면, bind는 함수 객체를 리턴 하는 함수라는 것이다. 만약 리턴 값을 얻고 싶다면, 그 함수 객체를 operator() 를 수행해야 한다. bind가 너무 유연하다보니, 여기서 햇갈렸다.
총 정리 코드
- #include <boost/bind.hpp>
- #include <boost/ref.hpp>
- #include <iostream>
- using boost::bind;
- using boost::ref;
- using boost::cref;
- int f(int a, int b)
- {
- return a + b;
- }
- int main()
- {
- int i = 5;
- // operator()( 5, x ) 로 수행 되는 함수 객체 리턴
- bind(f, i, _1);
- // operator()(&i, x ) 로 수행 되는 함수 객체 리턴
- // 만약 f의 내부에서 i를 변경시킨다면 i 에 5가 아닌 다른 값이 들어 갈 수 있다.
- bind(f, ref(i), _1);
- // 이것은 무엇이지?
- bind(f, cref(42), _1)(1, 2, 3, 4, 5, 6, 7, 8, 9 );
- }
이 코드의 ref 와 cref 는 전달 된 인자를 reference 로 바꾸거나 const reference 로 바꾸어 주는 함수이다. 눈 여겨 볼 것은 마지막 27 라인의 코드이다. 여기서 _1 부분, 즉 1만 인식되고, 나머지는 무시 된다. 이것은 만들어진 함수 객체에 최대 9개까지인자로 전달 될 수 있다는 것을 의미한다.
여기까지가 일반 함수를 bind 하여, 객체 함수를 만드는 방법이다. 그렇다면, 함수 포인터는 어떻게 할 수 있을까? 다음 코드를 보자.
- #include <boost/bind.hpp>
- #include <iostream>
- using boost::bind;
- int f(int a, int b)
- {
- return a + b;
- }
- int main()
- {
- // 함수 포인터형 선언
- typedef int (*FUNCPOINTER)( int, int );
- // 포인터에 f 를 대입
- FUNCPOINTER funcpointer = f;
- // 결과 확인
- std::cout << bind( funcpointer, 1, 2 )();
- }
.. 이것으로 일반 함수나, 함수 포인터를 어떻게 bind 시켜서 함수 객체로 만들고, 변형 시키는 방법을 알아 보았다. 다음 파트 2에선 함수 객체를 어떻게 해보는지 알아 본다.
총평
역시 공부는 정리할 때 더 많이 알아 가는것 같다. STL 를 사용 한다면, bind 를 꼭 알고 넘어가야 하는 넘어 가야겠다는 생각이 든다. 템플릿 함수이다 보니, .. 그 소스 코드가 매우 보기 힘들지만, 이 정도는 만들 수 있어야 " 나 템플릿 좀 써봤지" 라고 말 할 수 있을 것 같다.
출처 : http://ikpil.com/695
위의 정보가 도움이 되셨나요? 그렇다면 댓글 하나만 남겨주세요.
댓글 하나가 운영자에겐 커다란 힘이 됩니다!
- Filed under : 프로그래밍/C & Cpp
- Comment Trackback

