반응형

2008/11/04 19:14 IT 연구실/Boost.org
Bind 는 임의의 함수 포인터나 함수에 국한되지 않고, 함수 객체도 bind 할 수 있게 해 준다. 이 함수 객체를 바인드 할 경우 operator() 의 리턴 타입을 명시적으로 bind 함수에 알려 줘야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <boost/bind.hpp>
 
struct F
{
    int operator()(int a, int b) { return a - b; }
    bool operator()(long a, long b) { return a == b; }
};
 
int main( void )
{
    F f;
 
    int x = 104;
 
    bind<int>(f, _1, _1)(x);      // f(x, x), i.e. zero
 
    return 0;
}

이 처럼 bind<Return-type>(...) 을 지정해 주어야 bind 함수는 객체를 생성 할 수 있게 된다. 여기서 유심히 봐야 할 부분은 F::operator() 에 2개의 오버로드된 함수가 있는데, 이때 바인드시 전달되는 x의 타입으로 결정 되어 진다.

일반적인 함수 오버로딩과 똑같다고 생각하면 쉽게 이해가 된다.

만약, 위의 코드가 컴파일시 문제가 된다면, 아래와 같은 방법으로 컴파일 해야 할 것이다. 왜냐하면, 컴파일 마다 템플릿 구문 해석기의 구문 해석이 다르기 때문이다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <boost/bind.hpp>
 
struct F
{
    int operator()(int a, int b) { return a - b; }
    bool operator()(long a, long b) { return a == b; }
};
 
int main( void )
{
    F f;
 
    int x = 104;
 
    // 이렇게
    boost::bind(boost::type<int>(), f, _1, _1)(x);
 
 
    return 0;
}

이제 함수 객체를 bind 시키는 방법을 알아 보았다면, 여기서 한가지 더 알린다면, 그 함수 객체에 result_type 이 정의 되어 있다면, 이 반환 타입을 무시할 수 있다. 예를 들자면 less<T>() 함수 객체의 경우 내부에 result_type 이 bool 로 정의 되어 있다.

이렇게 이야기 하면 .. 햇갈리니 코드를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <boost/bind.hpp>
#include <iostream>
 
struct F
{
    typedef int result_type;
    int operator()(int a, int b) { return a - b; } 
};
 
int main( void )
{
    F f;
 
    int x = 104;
 
    std::cout << boost::bind(f, _1, _2)(1,2);
 
    return 0;
}

하지만, 이 result_type 이 있다고 해서 모든 컴파일러가 되는 것은 아니기 때문에, 알아 두길 바란다.


여기서 bind 가 함수 객체를 받아 들였다면, 이 함수 객체를 "복사" 해서 내부적으로 가지고 있고, 그것을 사용 하게 된다. 이 때, 이 복사 하는 비용이나, 특별히 상태를 갖어야 하는 함수 객체라면, boost::ref(x) 이나 boost::cref(x)로 전달 하는것이 좋을 것이다.

이 경우, 특별히 주의 해야 할 것은, 레퍼런스 copy가 이루어 지기 때문에, 이 사실을 필히 알고 있어야 한다.(내부적으로 상태가 변한다. 또한 임시 객체의 경우, 그 소멸시점에 대해 정확히 꾀차고 있어야 한다.)


예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <boost/bind.hpp>
#include <algorithm>
#include <assert.h>
 
struct F2
{
    int s;
 
    typedef void result_type;
    void operator()( int x ) { s += x; }
};
 
int main( void )
{
    F2 f2 = { 0 };
    int a[] = { 1, 2, 3 };
 
    std::for_each( a, a+3, boost::bind( boost::ref(f2), _1 ) );
 
    assert( f2.s == 6 );
 
    return 0;
}


총평

함수 객체의 경우, 함수의 리턴값을 정해줘야 한다는 사실과, result_type을 제공한다면, 생략될 수 있다는 것을 보boo고 boost::mem_fn 이나, stl 객체 함수를 사용 한다면, 그냥 들어 가겠다 싶다. 역시 boost. 완전 사랑해

반응형

'메타프로그래밍 > Boost::' 카테고리의 다른 글

boost::boost::unordered_map, unordered_set  (0) 2013.03.02
boost::bind, boost::mem_fn, boost::ref 조합  (0) 2013.03.01
boost::circular_buffer  (0) 2013.02.26
boost::any  (0) 2013.02.13
boost::variant  (0) 2013.02.13

+ Recent posts