boost::function의 간단한 실현
5851 단어 function
앞말
boost:::function과 boost:bind는 강력한 이기입니다.사용한 구두는 다소 체득할 수 있다고 믿는다.
평소에 boost::function을 사용하지만 사용할 때 항상 불안합니다. 어떻게 이루어졌는지 모르기 때문입니다.그래서 간단한 실현을 스스로 궁리하며 기본적인 원리를 깨달았다.
이 간단한 실현에 대해 다음과 같은 몇 가지 목표가 있다.
실현
먼저 기본 클래스를 정의합니다.
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
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
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 형식은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
출력된 내용이 바로 기대하는 결과임을 알 수 있다.
참고 문헌
(끝)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
콜백 함수를 Angular 하위 구성 요소에 전달이 예제는 구성 요소에 함수를 전달하는 것과 관련하여 최근에 직면한 문제를 다룰 것입니다. 국가 목록을 제공하는 콤보 상자 또는 테이블 구성 요소. 지금까지 모든 것이 구성 요소 자체에 캡슐화되었으며 백엔드에 대한 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.