boost::function의 간단한 실현

5851 단어 function

앞말


boost:::function과 boost:bind는 강력한 이기입니다.사용한 구두는 다소 체득할 수 있다고 믿는다.
평소에 boost::function을 사용하지만 사용할 때 항상 불안합니다. 어떻게 이루어졌는지 모르기 때문입니다.그래서 간단한 실현을 스스로 궁리하며 기본적인 원리를 깨달았다.
이 간단한 실현에 대해 다음과 같은 몇 가지 목표가 있다.
  • 비교적 흔히 볼 수 있는 수신 매개 변수 2개를 선택한 경우..
  • 일반 함수/함수 포인터, 구성원 함수 포인터 지원..
  • 호환 함수 대상, 함수 어댑터/boost::bind..

  • 실현


    먼저 기본 클래스를 정의합니다.
    template<typename R, typename T1, typename T2>
    
    class base
    
    {
    
    public:
    
        virtual ~base()
    
        {
    
        }
    
    
    
        virtual R operator()(T1, T2) = 0;
    
    };

    그리고 일반 함수/함수 바늘의 버전을 다시 실현합니다.
    template<typename R, typename T1, typename T2>
    
    class func : public base<R, T1, T2>
    
    {
    
    public:
    
        func(R (*ptr)(T1, T2))
    
            : ptr_(ptr)
    
        {
    
        }
    
    
    
        virtual R operator()(T1 a, T2 b)
    
        {
    
            return ptr_(a, b);
    
        }
    
    
    
    private:
    
        R (*ptr_)(T1, T2);
    
    };

    다음 버전에서는 구성원 함수 포인터를 지원합니다.
    template<typename R, typename Class, typename T>
    
    class member : public base<R, Class, T>
    
    {
    
    };
    
    
    
    template<typename R, typename Class, typename T>
    
    class member<R, Class*, T> : public base<R, Class*, T>
    
    {
    
    public:
    
        member(R (Class::*ptr)(T))
    
            :    ptr_(ptr)
    
        {
    
        }
    
    
    
        virtual R operator()(Class* obj, T a)
    
        {
    
            return (obj->*ptr_)(a);
    
        }
    
    
    
    private:
    
        R (Class::*ptr_)(T);
    
    };

    어떤 아동화는 왜 여기에 빈 멤버류가 있는지 물어봐야 할 것 같다.이 문제는 아래에 놓고 해석해라.
    자연스럽게 마지막 상황, 함수 대상/boost::bind 형식:
    template<typename T, typename R, typename T1, typename T2>
    
    class functor : public base<R, T1, T2>
    
    {
    
    public:
    
        functor(const T& obj)
    
            : obj_(obj)
    
        {
    
        }
    
    
    
        virtual R operator()(T1 a, T2 b)
    
        {
    
            return obj_(a, b);
    
        }
    
    
    
    private:
    
        T obj_;
    
    };

    마지막으로 사용할 수 있는 function 클래스입니다. 다음과 같습니다.
    template<typename T>
    
    class function
    
    {
    
    };
    
    
    
    template<typename R, typename T1, typename T2>
    
    class function<R (T1, T2)>
    
    {
    
    public:
    
        template<typename Class, typename _R, typename _T2>
    
        function(_R (Class::*ptr)(_T2))
    
            : ptr_(new member<R, T1, T2>(ptr))
    
        {
    
        }
    
    
    
        template<typename _R, typename _T1, typename _T2>
    
        function(_R (*ptr)(_T1, _T2))
    
            : ptr_(new func<R, T1, T2>(ptr))
    
        {
    
        }
    
    
    
        template<typename T>
    
        function(const T& obj)
    
            : ptr_(new functor<T, R, T1, T2>(obj))
    
        {
    
        }
    
    
    
        ~function()
    
        {
    
            delete ptr_;
    
        }
    
    
    
        virtual R operator()(T1 a, T2 b)
    
        {
    
            return ptr_->operator()(a, b);
    
        }
    
    
    
    private:
    
        base<R, T1, T2>* ptr_;
    
    };

    보시다시피 앞의 멤버 클래스와 마찬가지로function에도 빈 클래스가 있습니다. 그러면 이게 무슨 소용이 있을까요?
    이렇게 하는 이유는 주로 템플릿의 편차를 이용하여 유형 추출을 하는 것이다. 정상적인 function 성명을 할 때, 예를 들어function이func가 아니라.그래서 템플릿의 특화된 버전을 사용합니다.
    template<typename R, typename T1, typename T2>
    
    class function<R (T1, T2)>

    인트(int, int)를 R = int, T1 = int, T2 = int로 추출할 수 있습니다.
    같은 이치로 member 클래스에 대해 일반적으로 우리가 구성원 함수 바늘을 function에 연결할 때, 예를 들어 int function (Type*, int), 그 중에서 Type는 구성원 함수가 속하는 클래스이기 때문이다.그러니까 function에 있는 멤버 ptr_.의 유형은base입니다. 그러면 function의 구조 함수에서 구조된member류의 유형은member입니다. 즉, Class=Type*입니다. 그러나 우리가 필요로 하는 것은 Class=Type입니다.그래서 이곳은 편특화로 추출해야 한다.
    template<typename R, typename Class, typename T>
    
    class member<R, Class*, T> : public base<R, Class*, T>

    이렇게 하면 Class 템플릿 인삼은 컴파일러에 의해 Type*가 아닌 Type으로 결정됩니다.
    그리고 function의 3가지 상황의 구조 함수는 템플릿 구성원 함수이지 일반 구성원 함수가 아니다.
        template<typename Class, typename _R, typename _T2>
    
        function(_R (Class::*ptr)(_T2))
    
            : ptr_(new member<R, T1, T2>(ptr))
    
        {
    
        }
    
    
    
        template<typename _R, typename _T1, typename _T2>
    
        function(_R (*ptr)(_T1, _T2))
    
            : ptr_(new func<R, T1, T2>(ptr))
    
        {
    
        }
    
    
    
        template<typename T>
    
        function(const T& obj)
    
            : ptr_(new functor<T, R, T1, T2>(obj))
    
        {
    
        }

    두 가지 상황에서 일반 함수/함수 바늘에 대응하는 구조 함수와 구성원 함수 바늘에 대응하는 구조 함수는 구성원 템플릿으로 이루어진다. 주로 매개 변수를 호환하기 위한 스텔스 변환이다. 예를 들어 하나의 function 형식은functionfoo이고 호출할 때 두 개의 더블 형식,foo(1.1,2.2),double 형식은 int 형식으로 변환된다.이것도 boost:function 원래의 호환 가능한 호출물이라는 특성에 부합된다.
    세 번째 상황의 구성원 템플릿은 전송된 함수 대상/boost::bind의 형식을 가져와functor의 데이터 구성원에 저장하기 위해서입니다. 이것도 functor류의 템플릿 파라미터가 다른 버전보다 많은 이유입니다.
    그리고 테스트를 해보겠습니다.
    int get(int a, int b)
    
    {
    
        std::cout << a+b << std::endl;
    
        return 0;
    
    }
    
    
    
    class Point
    
    {
    
    public:
    
        int get(int a)
    
        {
    
            std::cout << "Point::get called: a = "<< a << std::endl;
    
            return a;
    
        }
    
        int doit(int a, int b)
    
        {
    
            std::cout << "Point::doit called: a = "<< a+b << std::endl;
    
            return a+b;
    
        }
    
    };
    
    
    
    int main(int argc, char const *argv[])
    
    {
    
        function<int (int, int)> foo(get);
    
        foo(10.1, 10.3);
    
    
    
        function<int (Point*, int)> bar(&Point::get);
    
        Point point;
    
        bar(&point, 30);
    
    
    
        function<int (int, int)> obj(boost::bind(&Point::doit, &point, _1, _2));
    
        obj(90, 100);
    
    }

    결과는 다음과 같습니다.
    20
    
    Point::get called: a = 30 Point::doit called: a = 190

    출력된 내용이 바로 기대하는 결과임을 알 수 있다.

    참고 문헌

  • 부스트 중국어 안내서.  Improved Function Object Adapters 개량된 함수 객체 어댑터

  • (끝)

    좋은 웹페이지 즐겨찾기