首页 > 解决方案 > 转发到 std::async

问题描述

这是我试图调用异步转发参数的(简化)代码:

template<typename Ret, typename ... Args>
class CallbackAsyncTask {
public:
    CallbackAsyncTask() {
    }
    virtual ~CallbackAsyncTask() = default;

    void execute( Args&& ... args ) {
        execute(&CallbackAsyncTask<Ret, Args...>::onBackground, this, std::forward<Args>(args)...);
    }
protected:
    virtual Ret onBackground( Args& ... args ) = 0;
    template<typename Fn, typename ... Argss>
    void execute( Fn&& fn, Argss&& ... args ) noexcept(false) {
        std::async(std::launch::async, std::forward<Fn>(fn), std::forward<Argss>(args)...);
    }
};

class Child: public CallbackAsyncTask<int, int> {
public:
    virtual int onBackground( int& i ) {
        return i;
    }
};

int main() {
    Child c;
    c.execute(15);
    return 0;
}

我收到此错误:

../main.cpp: In instantiation of ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’:
../main.cpp:27:98:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17:   required from here
../main.cpp:33:90: error: no matching function for call to ‘async(std::launch, int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>* const, int)’
         std::async(std::launch::async, std::forward<Fn>(fn), std::forward<Argss>(args)...);
                                                                                          ^
../main.cpp:33:90: note: candidates are:
In file included from ../main.cpp:13:0:
/usr/include/c++/4.8.2/future:1532:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
     async(launch __policy, _Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/4.8.2/future:1532:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.8.2/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = int (CallbackAsyncTask<int, int>::*)(int&); _Args = {CallbackAsyncTask<int, int>* const, int}]’:
../main.cpp:33:90:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’
../main.cpp:27:98:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17:   required from here
/usr/include/c++/4.8.2/future:1532:5: error: no type named ‘type’ in ‘class std::result_of<int (CallbackAsyncTask<int, int>::*(CallbackAsyncTask<int, int>*, int))(int&)>’
../main.cpp: In instantiation of ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’:
../main.cpp:27:98:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17:   required from here
/usr/include/c++/4.8.2/future:1552:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...)
     async(_Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/4.8.2/future:1552:5: note:   template argument deduction/substitution failed:
/usr/include/c++/4.8.2/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>* const, int}]’:
../main.cpp:33:90:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’
../main.cpp:27:98:   required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17:   required from here
/usr/include/c++/4.8.2/future:1552:5: error: no type named ‘type’ in ‘class std::result_of<std::launch(int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>*, int)>’

我错过了什么?编译器GCC 4.8.3

标签: c++c++11

解决方案


根本原因是这两行

virtual Ret onBackground( Args& ... args ) = 0;

virtual int onBackground( int& i )

启动任务时,参数要么直接转换,要么像std::thread构造函数一样转换。在调用可调用对象时对decay_copy参数执行此操作,因此非常量左值引用不能绑定到参数。

改变onBackground接受参数的方式。例如,一个 const 左值引用有效。看直播


推荐阅读