2011-08-01 38 views
0

我需要一個std :: bind函數包裝器,它將在包裝函數之前調用,並將參數傳遞給包裝函數。在C++中爲std :: bind函數裝飾器0x

std::function<void (int)> foo = postbind<int>(service, handle); 

我這麼遠下來到

std::function<void (int)> foo = postbind(service, handle); 

我如何刪除模板參數?它似乎歸結爲從對象生成函數(postbind)中扣除的類型不夠智能。

#include <functional> 

template<typename T> 
void foo(std::function<void (T)> func) 
{ 
} 

void handler(int x) 
{ 
} 

int main() 
{ 
    foo(handler); 
    return 0; 
} 

說錯誤:調用 '富(無效(&)(INT))'

沒有匹配的功能然而,代碼示例:

template<typename T> 
void foo(T t) 
{ 
} 

int main() 
{ 
    foo(99); 
    return 0; 
} 

這工作。任何想法如何使這項工作?我需要能夠將std :: bind傳遞給它,並將結果成功轉換爲std :: function。

如何刪除模板參數?謝謝。


問:什麼是服務,這個班意味着什麼? A.將封裝了boost :: asio :: io_service->的函數封裝封裝到當前線程之外。


全部源代碼:

#include <iostream> 
#include <functional> 
#include <memory> 

class io_service 
{ 
}; 

typedef std::shared_ptr<io_service> service_ptr; 

template <typename Arg1> 
class postbind_impl_1 
{ 
public: 
    typedef std::function<void (Arg1)> function; 

    postbind_impl_1(service_ptr service, function memfunc) 
     : service_(service), memfunc_(memfunc) 
    { 
    } 

    void operator()(Arg1 arg1) 
    { 
     // do stuff using io_service 
     memfunc_(arg1); 
    } 
private: 
    service_ptr service_; 
    function memfunc_; 
}; 

template <typename Arg1> 
postbind_impl_1<Arg1> postbind(service_ptr service, 
     typename postbind_impl_1<Arg1>::function handle) 
{ 
    return postbind_impl_1<Arg1>(service, handle); 
} 

// ---------------- 

void handle(int x) 
{ 
    std::cout << x << "\n"; 
} 

int main() 
{ 
    service_ptr service; 
    std::function<void (int)> foo = postbind(service, handle); 
    foo(110); 
    return 0; 
} 
+0

什麼是'service'和'handle'?你能舉一個預期用法的例子嗎? –

+0

在上面解答了您的問題。 ATM我使用std :: bind函數將一個函數傳遞給一個操作,該操作在完成後調用句柄(...)(即handle_connect)。如果handle_connect是在單獨線程中運行的api的一部分,那麼我在內部需要將handle_connect發佈到do_handle_connect以便切換線程 - 醜陋。我寧願有一個自動包裝器,在其中傳遞io_service。 – genjix

回答

0

所有誰說,這是不可能的:)反對者

/* 
* Defines a function decorator ala Python 
* 
* void foo(int x, int y); 
* function<void()> wrapper(function<void (int)> f); 
* 
* auto f = decorator(wrapper, bind(foo, 110, _1)); 
* f(); 
*/ 

#include <functional> 

template <typename Wrapper, typename Functor> 
struct decorator_dispatch 
{ 
    Wrapper wrapper; 
    Functor functor; 

    template <typename... Args> 
    auto operator()(Args&&... args) 
     -> decltype(wrapper(functor)(std::forward<Args>(args)...)) 
    { 
     return wrapper(functor)(std::forward<Args>(args)...); 
    } 
}; 

template <typename Wrapper, typename Functor> 
decorator_dispatch< 
    Wrapper, 
    typename std::decay<Functor>::type 
> 
decorator(Wrapper&& wrapper, Functor&& functor) 
{ 
    return {wrapper, functor}; 
} 
0

我不能完全確定你想要達到的,但這裏有一個天真的包裝,存儲的操作的列表:

template <typename R, typename A> 
struct wrap 
{ 
    typedef std::function<R(A)> func; 

    wrap(func f_) : f(f_) { } 

    void prebind(func g) { prebound.push_back(g); } 

    R operator()(A arg) 
    { 
    for (auto it = prebound.cbegin(); it != prebound.cend(); ++it) 
    { 
     func g = *it; 
     g(arg); 
    } 

    f(arg); 
    } 
private: 
    std::vector<func> prebound; 
    func f; 
}; 

wrap<void, int> make_wrap(std::function<void(int)> f) 
{ 
    return wrap<void, int>(f); 
} 

用法:

auto foowrap = make_wrap(foo); 

foowrap.prebind(std::function<void(int)>(action1); 
foowrap.prebind(std::function<void(int)>(action2); 

foowrap(12); // calls action1(12), action2(12), foo(12) 
+0

現在嘗試模板你的函數make_wrap,所以你不必提供任何模板參數,它可以從foo自動推斷出類型。 – genjix

+0

嗯,等等,我想我錯了 - 你應該已經可以從'make_wrap'中省略模板參數了。讓我編輯。 –

+0

這就是問題: 模板 的std ::函數 make_wrap(標準::函數 F) { 返回包裹(F); } 該模板參數化了您的功能。現在稱之爲不帶模板參數: auto foowrap = make_wrap(foo); – genjix

2

喲如何你希望編譯器知道使用std::function?在此代碼:

#include <functional> 

template<typename T> 
void foo(T func) 
{ 
} 

void handler(int x) 
{ 
} 

int main() 
{ 
    foo(handler); 
    return 0; 
} 

Tstd::function<void (int)>。它是void (&)(int)(就像所說的錯誤信息),是對函數的引用,而不是函子對象。

參數類型的傳遞函數應該工作的扣除,請嘗試:

#include <functional> 

template<typename T> 
std::function<void (T)> foo(void (*func)(T)) 
{ 
} 

void handler(int x) 
{ 
} 

int main() 
{ 
    foo(handler); 
    return 0; 
} 

演示:http://ideone.com/NJCMS

如果您需要從任std::function或純函數指針提取的參數類型,你」會需要一個輔助結構:

template<typename> 
struct getarg {}; 

template<typename TArg> 
struct getarg<std::function<void (TArg)>> { typedef TArg type; }; 

template<typename TArg> 
struct getarg<void (*)(TArg)> { typedef TArg type; }; 

template<typename TArg> 
struct getarg<void (&)(TArg)> { typedef TArg type; }; 

template<typename T> 
std::function<void (typename getarg<T>::type)> foo(T func) 
{ 
} 

void handler(int x) 
{ 
} 

int main() 
{ 
    foo(handler); 
    return 0; 
} 

演示:http://ideone.com/jIzl7

用的C++ 0x,你也可以匹配任何隱式轉換爲std::function,包括std::bind返回值和lambda表達式:http://ideone.com/6pbCC

+0

問題在於,它不適用於std :: bind。即std :: function foo = postbind(service,std :: bind(handle,_1,9)); – genjix

+0

@user:我演示瞭如何使用部分特化和typedef來實現這一點,請參閱更新。 –

+0

令人驚歎!使用這些代理對象很有用。我怎樣才能得到std ::綁定到自動轉換爲std ::函數而不需要,std :: function b = postbind(service,std :: function (std :: bind(handle,_1,9))); – genjix

3

AFAICT參數類型綁定表達式都沒有抵扣,所以你想要什麼是很很不可能。