IT

std :: function 및 std :: bind : 무엇이며 언제 어디에서 가지고 있습니까?

lottoking 2020. 7. 29. 07:35
반응형

std :: function 및 std :: bind : 무엇이며 언제 어디에서 가지고 있습니까?


나는 functors가 무엇인지 알고 언제 std알고리즘 과 함께 있는지 알고 싶습니다 Stroustrup이 C ++ 11 FAQ 에서 언급 한 내용을 이해하지 .

누구나 어떤 것이 무엇 std::bind이고 std::function언제 사용 하는지 설명하고 다음을위한 몇 가지 예를 제시 할 수 있습니까?


std::bind부분 기능 적용을 위한 것 입니다.

즉, f3 개의 인수를 취하는 함수가 가정하십시오 .

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

참고 URL : https://stackoverflow.com/questions/6610046/stdfunction-and-stdbind-what-are-they-and-when-should-they-be-used

반응형