std :: function 및 std :: bind : 무엇이며 언제 어디에서 가지고 있습니까?
나는 functors가 무엇인지 알고 언제 std
알고리즘 과 함께 있는지 알고 싶습니다 Stroustrup이 C ++ 11 FAQ 에서 언급 한 내용을 이해하지 .
누구나 어떤 것이 무엇 std::bind
이고 std::function
언제 사용 하는지 설명하고 다음을위한 몇 가지 예를 제시 할 수 있습니까?
std::bind
부분 기능 적용을 위한 것 입니다.
즉, f
3 개의 인수를 취하는 함수가 가정하십시오 .
f(a,b,c);
다음과 같이 정의 된 두 개의 인수 만 취하는 새로운 함수가 필요합니다.
g(a,b) := f(a, 4, b);
g
함수의 "부분 응용 프로그램"입니다 f
. 중간 인수가 이미 지정되어 있습니다.
당신은 std::bind
얻을 수 있습니다 g
:
auto g = bind(f, _1, 4, _2);
이것은 실제로 functor 클래스를 작성하는 것보다 더 간결합니다.
링크 된 기사에 다른 예가 있습니다. 일반적으로 functor를 일부 알고리즘에 전달해야 할 때 사용합니다. 원하는 작업 을 거의 수행하지만 알고리즘이 사용하는 것보다 더 구성 가능한 (즉, 더 많은 변수를 사용 ) 함수 또는 기능 이 있습니다. 따라서 인수를 일부 매개 변수에 바인딩하고 알고리즘이 채울 나머지 부분은 그대로있다.
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));
여기서는 pow
두 가지 가지 변수를 취하고 모든 힘을 올릴 수 있습니다.
부분 함수 응용 프로그램이 아닌 경우 에 bind
따라 인수를 함수에 다시 정렬 할 수도 있습니다.
auto memcpy_with_the_parameters_in_the_right_flipping_order = bind(memcpy, _2, _1, _3);
API가 마음에 들지 않기 때문에 사용하지 않는 것이 좋지만 다음과 같은 실용적인 용도가 있습니다.
not2(bind(less<T>, _2, _1));
동일하지 않은 함수입니다 (총 주문 가정, blah blah). 이 예제는 일반적으로 (아닌이 연산자를 std::less_equal
사용 하므로 일관성이 없으면 <=
연산자 <
가 필요하므로 클래스 작성자를 방문해야 우리합니다.) 기능적인 프로그래밍 스타일을 사용하는 경우 나타나는 일종의 변형입니다 .
std :: function std :: bind의 주요 용도 및 중 하나는보다 일반적인 함수 포인터입니다. 사용을 구현하는 데 사용할 수 있습니다. 인기있는 시나리오 중 하나는 실행하는 데 리턴하기를 기다리지 않고 완료하는 데 리턴하기를 기다리지 있습니다. 즉, 일련에서 해당 함수를 실행하고 함수 포인터를 할 수있는 것입니다 완료 후 제공합니다
사용 방법에 대한 샘플 코드는 다음과 가능합니다.
class MyClass {
private:
//just shorthand to avoid long typing
typedef std::function<void (float result)> TCallback;
//this function takes long time
void longRunningFunction(TCallback callback)
{
//do some long running task
//...
//callback to return result
callback(result);
}
//this function gets called by longRunningFunction after its done
void afterCompleteCallback(float result)
{
std::cout << result;
}
public:
int longRunningFunctionAsync()
{
//create callback - this equivalent of safe function pointer
auto callback = std::bind(&MyClass::afterCompleteCallback,
this, std::placeholders::_1);
//normally you want to start below function on seprate thread,
//but for illustration we will just do simple call
longRunningFunction(callback);
}
};
std :: bind는 boost bind를 제안 제안한 후 라이브러리에 투표합니다. 대부분의 부분 함수는 다음 변수를 거의 수정하지 않고 다음 변수를 즉시 설명 수 있습니다. 이제 이것은 C ++에서 람다를 수행하는 라이브러리 방식입니다. 답변으로 Steve Jessop
이제 C ++ 11이 람다 함수를 지원하므로 더 이상 std :: bind를 사용하고 싶은 유혹을 느끼지 않습니다. 나는 도서관 기능보다는 언어 기능이있는 카레 (부분 전문화)를 사용하고 싶다.
std :: function 객체는 다형성 함수입니다. 기본 아이디어는 모든 호출 가능한 객체를 상호 교환 적으로 참조 할 수 있다는 것입니다.
자세한 내용은 다음 두 링크를 알려 드리겠습니다.
C ++ 11의 Lambda 함수 : http://www.nullptr.me/2011/10/12/c11-lambda-having-fun-with-brackets/#.UJmXu8XA9Z8
C ++의 호출 가능 엔티티 : http://www.nullptr.me/2011/05/31/callable-entity/#.UJmXuMXA9Z8
나는 C ++에서 플러그인 스레드 풀을 만들기 위해 오랫동안 사용했다. 함수가 세 개의 매개 변수를 취했기 때문에 다음과 같이 작성할 수 있습니다.
메서드에 서명이 있다고 가정합니다.
int CTask::ThreeParameterTask(int par1, int par2, int par3)
세 개의 매개 변수를 바인딩하는 함수 객체를 만들려면 다음과 같이 할 수 있습니다.
// a template class for converting a member function of the type int function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
:m_Ptr(_Pm) //okay here we store the member function pointer for later use
{}
//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
이제 매개 변수를 바인딩하기 위해 바인더 함수를 작성해야합니다. 그래서 여기에 간다 :
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
:m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}
//and this is the function object
void operator()() const
{
m_fn(m_ptr,m1,m2,m3);//that calls the operator
}
private:
_Ptr m_ptr;
_Func m_fn;
_arg1 m1; _arg2 m2; _arg3 m3;
};
그리고 binder3 클래스를 사용하는 도우미 함수-bind3 :
//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}
그리고 여기서 우리는 그것을 부르는 방법
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3(
&CTask::ThreeParameterTask), task1,2122,23 );
참고 : f3 (); task1-> ThreeParameterTask (21,22,23) 메소드를 호출합니다.
자세한 내용은-> http://www.codeproject.com/Articles/26078/AC-Plug-in-ThreadPool-Design
'IT' 카테고리의 다른 글
인터페이스 상수의 사용은 무엇입니까? (0) | 2020.07.29 |
---|---|
프래그먼트 분리와 제거의 차이점은 무엇입니까? (0) | 2020.07.29 |
HashSet은 요소와 동등성을 어떻게 비교합니까? (0) | 2020.07.29 |
CSS 배경 이미지 대체 속성 (0) | 2020.07.29 |
.NET 고유 객체 식별자 (0) | 2020.07.29 |