2012-06-20 55 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要绑定到。每个函数模板的实例都有一个。