2012-06-20 54 views
3

我已經嘗試了VS,g ++和Clang的以下內容,並且無法對任何錯誤進行韻律或原因分析。如何綁定異步?

void foo() {} 

auto f = bind(async, foo); 

我懷疑錯誤可能從哪個異步()結合,一,需要一個啓動策略對不適用的一個混亂幹......或者我必須明確給出異步( )它的模板類型(例如async < ...>)?無論哪種方式,編寫上述語句的正確方法是什麼?

編輯:

感謝您的建議傢伙,但沒有了以下工作(與任何編譯器)的:

bind(async<decltype(foo)>, foo); 

bind(async<void (*)()>, foo); 

bind(async<function<void()> >, foo); 
+4

是的,你需要通過模板參數。我只會使用lambda並忘記綁定。 –

+1

也許試試'async '。 –

回答

2

std::async不僅是一個模板,但它也被重載。您不僅需要選擇所需的模板,還需要選擇超載。

typedef decltype(&foo) foo_type; 
typedef std::result_of<foo_type()>::type foo_rettype; 

auto chosen_async= 
    static_cast<std::future<foo_rettype> (*)(foo_type &&)> 
    (&std::async<foo_type>); 

不幸的是,std::bind似乎並沒有允許綁定功能服用右值引用。所以只寫std::bind(chosen_async, &foo)仍然不行。此問題的解決辦法是在Is there a reference_wrapper<> for rvalue references?討論:

template<typename T> struct adv { 
    T t; 
    explicit adv(T &&t):t(std::forward<T>(t)) {} 
    template<typename ...U> T &&operator()(U &&...) { 
    return std::forward<T>(t); 
    } 
}; 

template<typename T> adv<T> make_adv(T &&t) { 
    return adv<T>{std::forward<T>(t)}; 
} 

namespace std { 
    template<typename T> 
    struct is_bind_expression< adv<T> > : std::true_type {}; 
} 

我們會說std::bind(chosen_async, make_adv(std::move(&foo))),除了一個問題來實現:你不能直接傳遞std::async我們的包裝對象之一,因此std::result_of<...>(因此std::bind )。不能推斷出chosen_async會返回。因此,我們明確聲明的返回類型:

auto async_bound= 
    std::bind<std::future<foo_rettype>>(chosen_async, 
             make_adv(std::forward<foo_type>(&foo))); 

做這一切似乎足以讓GCC快樂,至少:http://ideone.com/gapLs


當然,你可以保存自己噸麻煩與lambda表達式:

auto async_bound=[=]()->std::future<void> {return std::async(&foo);}; 
+0

它現在運行。這也超級醜陋。有人建議使用lambda表達式嗎? ;-) – Managu

+0

@Managu感謝您爲調查工作所做的努力(並且顯示它並不是那麼簡單 - 「爲其提供模板參數」)。現在,要告訴你實情,當我偶然發現這個「問題」時,我有點不知所措。我對此沒有「現實世界」的需求。我試圖看看是否可以像auto f = bind(async,foo,_1); F(11)獲得(); F(22),獲得(); (這是壓縮版本)。在你回答之後,我不確定它是否可以優雅地完成......但是,你的答案仍然可能會在以後受益。那個人可能是你或我。 :) – screwnut

+0

@screwnut:我想的很多。並且lambdas仍然更好:'auto fooasync = [=](int i) - > decltype(async(&foo,i)){return async(&foo,i);}' – Managu

2

你必須給async模板參數。不只有一個async要綁定到。每個函數模板的實例都有一個。