2005-10-22

find_if 와 boost::lambda

STL 컨테이너를 만지작거리다보면 종종 algorithm 을 써서 코드를 간략하게 표현하고픈 충동이 든다. 그런데 STL에서 제공하는 각종 function template 의 파워는 생각보다 약하다. 가령 다음과 같이 컨테이너 내부 객체의 멤버 함수의 실행 결과를 기준으토 무언가를 하고 싶은 경우...

class Focker
{
public :
    Focker(int v) : value(v) {}
    int GetValue() const { return value; }
private:
    int value;
};

typedef list FOCKERS;

FOCKERS fockers;

fockers.push_back( Focker(1) );
fockers.push_back( Focker(2) );
fockers.push_back( Focker(3) );
fockers.push_back( Focker(4) );
fockers.push_back( Focker(5) );

// how to find whose value ==3 ??

가장 단순한 방법으로는 하드코딩 함수자를 사용하면 된다.

class GetValueIs3
{
public :
    GetValueIs3(){}
    bool operator() ( const Focker & f ) const
    {
        return f.GetValue() == 3;
    }
};

FOCKERS::iterator itr;

itr = find_if( fockers.begin(), fockers.end(), GetValueIs3() );
assert( itr != fockers.end() );
cout GetValue() GetValue() (),3),
        mem_fun_ref(&Focker::GetValue )) );

그래서 이걸 가능하게 하기 위해서 몇 시간동안 씨름하다가 mem_fun_ref 의 코드를 살짝 고쳐서 다음과 같은 코드를 만들어봤다.

template
class my_const_mem_fun_ref_t
    : public unary_function
{
public:
    explicit my_const_mem_fun_ref_t(_Result (_Ty::*_Pm)() const, const _Fn & f )
        : _Pmemfun(_Pm), func(f)
    {
    }

    typename _Fn::result_type operator()(const _Ty& _Left) const
    {
        return (func((_Left.*_Pmemfun)()));
    }

private:
    _Result (_Ty::*_Pmemfun)() const;   // the member function pointer
    _Fn func;
};

template
inline
my_const_mem_fun_ref_t
my_mem_fun_ref(_Result (_Ty::*_Pm)() const, const _Fn & f)
{
    return (my_const_mem_fun_ref_t(_Pm,f));
}

itr = find_if( fockers.begin(), fockers.end(),
    my_mem_fun_ref( &Focker::GetValue, bind2nd(equal_to(),3) )
);
assert( itr != fockers.end() );
cout GetValue() GetValue()

comments powered by Disqus