2013-03-10 4 views
1

boost :: function 및/또는 boost :: bind를 사용하여 다음 함수 포인터 전달을 단순화하거나 향상시킬 수 있습니까?boost 함수 포인터 인수 전달

void PassPtr(int (*pt2Func)(float, std::string, std::string)) 
{ 
    int result = (*pt2Func)(12, "a", "b"); // call using function pointer 
    cout << result << endl; 
} 

// execute example code 
void Pass_A_Function_Pointer() 
{ 
    PassPtr(&DoIt); 
} 
+1

당신이 찾고있는 답변의 종류에 따라 다릅니다! 물론, 위의 모든 것은'cout << DoIt (12, "a", "b") << endl;'으로 단순화 될 수 있습니다. 그러나 그것은 당신이 찾고있는 것이 아닌 것 같습니다. 즉, 함수 객체가 아닌 순수한 함수 포인터를 호출 할 때 Boost 기능을 활용할 수있는 확실한 기회가 없다는 것입니다. –

+0

그러면 어떤 멤버 함수 나 람다 (C++ 11 호환 컴파일러가있는 경우) 일반 함수 또는 정적 멤버 함수가 아닐 수도 있습니다.물론 boost :: bind (또는 [std :: bind'] (http://en.cppreference.com/w/cpp/utility/functional/bind))를 사용하면 어떤 숫자라도 "bind"할 수 있습니다 함수 객체를 전달하기 전에 인수를 사용해야합니다. –

+0

무엇이 고쳐지고 변경할 수 있습니까? 'PassPtr'와'DoIt'의 서명이 'no'로 고정되면 코드는 얻을 수있는만큼 간단합니다. –

답변

4

당신은 함수의 입력으로 호출 서로 다른 유형의 개체를 사용 가능하게하는 boost::function<>를 사용할 수 있습니다.

다음은 C++ 11을 사용하는 예제입니다 (이 예의 뒤에 설명 참조). 테스트 루틴 여기

int DoIt(float f, std::string s1, std::string s2) 
{ 
    std::cout << f << ", " << s1 << ", " << s2 << std::endl; 
    return 0; 
} 

int DoItWithFourArgs(float f, std::string s1, std::string s2, bool b) 
{ 
    std::cout << f << ", " << s1 << ", " << s2 << ", " << b << std::endl; 
    return 0; 
} 

struct X 
{ 
    int MemberDoIt(float f, std::string s1, std::string s2) 
    { 
     std::cout << "Member: " << f << ", " << s1 << ", " << s2 << std::endl; 
     return 0; 
    } 

    static int StaticMemberDoIt(float f, std::string s1, std::string s2) 
    { 
     std::cout << "Static: " << f << ", " << s1 << ", " << s2 << std::endl; 
     return 0; 
    } 
}; 

그리고있다 :

int main() 
{ 
    PassFxn(DoIt); // Pass a function pointer... 

    // But we're not limited to function pointers with std::function<>... 

    auto lambda = [] (float, std::string, std::string) -> int 
    { 
     std::cout << "Hiho!" << std::endl; 
     return 42; 
    }; 

    PassFxn(lambda); // Pass a lambda... 

    using namespace std::placeholders; 
    PassFxn(std::bind(DoItWithFourArgs, _1, _2, _3, true)); // Pass bound fxn 

    X x; 
    PassFxn(std::bind(&X::MemberDoIt, x, _1, _2, _3)); // Use a member function! 

    // Or, if you have a *static* member function... 
    PassFxn(&X::StaticMemberDoIt); 

    // ...and you can basically pass any callable object! 
} 

그리고 여기를

#include <functional> 
#include <string> 
#include <iostream> 

void PassFxn(std::function<int(float, std::string, std::string)> func) 
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
{ 
    int result = func(12, "a", "b"); // call using function object 
    std::cout << result << std::endl; 
} 

이들은 그것을 테스트하는 기능의 몇 가지가 있습니다 : 이것은 당신의 기능을 다시 것입니다 방법입니다 live example입니다.

비고 : 당신이 실제로 (C++ 03로 작업하는 경우

쉽게 boost::bind<>boost::function<>std::bind<>std::function<>을 변경할 수 Boost.Function을가 std::function<> 영감을 나중에 표준의 일부가되었다 무엇인가 C++ 라이브러리). 이 경우 <functional> 헤더를 포함하는 대신 boost::bind을 사용하려는 경우에만 boost/function.hppboost/bind.hpp 헤더를 포함해야합니다.

std::function<>/boost::function<>이 호출 가능한 객체를 캡슐화하는 기능을 제공한다는 또 다른 예를 보려면 this Q&A on StackOverflow을 참조하십시오.

+0

그게 전부! 내가 답을 표시하기 전에 하나의 추가 예제를 추가 할 수 있습니까? DoIt이 전달되는 멤버 함수 일 때 구문에서 어떻게 보입니까? – pingu

+0

@pingu : 가보고, 업데이트했습니다 :) –

+0

awesome! 덕분에 – pingu

3

사용자가 제공 한 모든 샘플 코드가 아닌 PassPtr의 기능을 개선한다고 가정합니다.

template <typename Func> 
void PassPtr(Func f) { 
    std::cout << f(12, "a", "b") << std::endl; 
} 

이 호출 가능한 객체가 f로 전달 될 수 있습니다 : 당신이 C++ (11)를 사용하고 람다 표현식을 사용할 수 있습니다 경우에, 나는 그냥하는 단순화 것이다. 추론 된 템플릿 유형에 의해 함수를 가져 오는 이유는 전달 된 모든 람다가 인라인되도록 허용하는 것입니다. 물론 이것은 전달 된 함수에 대한 특정 서명을 시행하지 않습니다 (또는 호출 가능한 객체 여야합니다). 예를 들어, int을 전달하면 혼란스러운 컴파일러 오류가 발생합니다.

void PassPtr(std::function<int(float, std::string, std::string)> f) { 
    std::cout << f(12, "a", "b") << std::endl; 
} 

이 호출 모든 종류의 객체가 바로 위와 같이, 전달 될 수 있지만, 아마도 람다가 인라인되는 원인이되지 않습니다 [boost|std]::function를 사용

대안은,이 작업을 수행하는 것입니다.