2013-03-25 4 views
-1

У меня есть некоторые функции C-стиля, которые возвращают 0, чтобы указать успех, и != 0 при ошибке.
Я хотел бы «обернуть» их в void функции, которые throw вместо того, чтобы возвращать значение.Общая функция bind() с Boost

Я написал этот помощник:

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

Затем обернуть детерминированную функцию int tilt(float degrees), я использую boost::bind:

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

И он прекрасно работает. Но я хотел бы иметь посвятить функцию обертки, так что я просто не могу сделать:

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

Он должен работать для любой функции/подписи, которая возвращает int.
Что было бы лучшим способом сделать это с помощью Boost?

+0

Может быть утомительным с C++, но с C++ 11, вы можете сделать это с помощью шаблонов varadic легко – 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 

Вот реализация С ++ 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', я вижу, что это делается именно так. Интересно ... –

Смежные вопросы