2013-03-25 2 views
-1

성공할 경우 0을 반환하고 오류시에는 != 0을 반환하는 C 스타일 함수가 있습니다.
void으로 값을 반환하는 대신 throw으로 "포장"하고 싶습니다.일반 함수 bind() with Boost

가 I이 도우미 쓴 :

function<void(float)> ntilt = bind(checkStatus, bind(tilt, _1)); 
ntilt(30); // this will call checkStatus(tilt(30)) 

을 그리고 그것은 잘 작동 :

다음
void checkStatus(int status) { 
    if (status != 0) 
    // throw an error object 
} 

이 확정 기능 int tilt(float degrees)을 포장하기를, 나는 boost::bind를 사용합니다. 그러나 나는 헌정 래퍼 기능을 가지고 싶습니다, 그래서 나는 다만 수

function<void(float)> ntilt = wrap(tilt); 
ntilt(30); // this will call checkStatus(tilt(30)) 

그것은 int 반환하는 모든 기능/서명 작동합니다.
부스트를 사용하여 가장 좋은 방법은 무엇입니까?

+0

C++에서는 지루할 수도 있지만 C++ 11에서는 가변적 인 템플릿을 사용하여 쉽게이 작업을 수행 할 수 있습니다. – dchhetri

+0

C++ 11을 사용하고 있지만 가능한 경우 C++ 솔루션에도 관심이 있습니다. . –

+0

잠깐,'bind (checkStatus, bind (tilt, _1));'잘 동작합니까? –

답변

3

당신은 당신의 포장의 기능이 걸릴 수 있습니다 매개 변수의 서로 다른 양을 처리 할 수있는 몇 가지 오버로드를 만들 수 있습니다

// handles 1 parameter functions 
template<typename Ret, typename T0> 
function<void(T0)> wrap(Ret (*fun)(T0)) { 
    return bind(checkStatus, bind(fun, _1)); 
} 

// handles 2 parameters functions  
template<typename Ret, typename T0, typename T1> 
function<void(T0, T1)> wrap(Ret (*fun)(T0, T1)) { 
    return bind(checkStatus, bind(fun, _1, _2)); 
} 

// ... add more 

는 여기에 C++ (11)의 구현입니다. 당신이 std::function을하지 않은 경우 당신은 몇 가지 물건을 피할 수 있지만, 잘, 그것은 작동 :

#include <functional> 
#include <stdexcept> 

template<typename Ret, typename... Args> 
struct wrapper { 
    typedef Ret (*function_type)(Args...); 

    void operator()(Args&&... args) { 
     if(fun(std::forward<Args>(args)...) != 0) 
      throw std::runtime_error("Error"); 
    } 

    function_type fun; 
}; 

template<typename Ret, typename... Ts> 
std::function<void(Ts...)> wrap(Ret (*fun)(Ts...)) { 
    return std::function<void(Ts...)>(wrapper<Ret, Ts...>{fun}); 
} 

Here 라이브 데모입니다.

+0

... C++ 0x로 할 수있는 더 좋은 방법이 있습니까? 답변 해주셔서 감사합니다. –

+0

흠, 가변성 템플릿을 사용하면 필요한 모든 자리 표시자를 바인딩해야합니다. – mfontanini

+0

'bind' 자신의 구현을 살펴보면, 정확하게 그렇게 된 것을 볼 수 있습니다. 흥미로운 ... –

관련 문제