C++ std::async的奇怪行为

C++ std::async的奇怪行为,c++,gcc,c++11,stdasync,C++,Gcc,C++11,Stdasync,考虑以下示例代码: #include <future> #include <array> #include <cassert> typedef std::array<int, 5> foo_t; foo_t* bar(foo_t& foo) { return &foo; } int main() { foo_t foo; auto a = std::async(bar, foo); auto b = s

考虑以下示例代码:

#include <future>
#include <array>
#include <cassert>

typedef std::array<int, 5> foo_t;

foo_t* bar(foo_t& foo) {
   return &foo;
}

int main() {
   foo_t foo;
   auto a = std::async(bar, foo);
   auto b = std::async(bar, foo);
   assert(a.get() == b.get());
   return 0;
}
但是,GCC 4.8.2拒绝编译该文件:

In file included from /usr/local/include/c++/4.8.2/future:38:0,
                 from test.cpp:1:
/usr/local/include/c++/4.8.2/functional: In instantiation of 'struct std::_Bind_simple<std::array<int, 5ul>* (*(std::array<int, 5ul>))(std::array<int, 5ul>&)>':
/usr/local/include/c++/4.8.2/future:1525:70:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = std::array<int, 5ul>* (&)(std::array<int, 5ul>&); _Args = {std::array<int, 5ul>&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = std::array<int, 5ul>*]'
/usr/local/include/c++/4.8.2/future:1541:36:   required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::array<int, 5ul>* (&)(std::array<int, 5ul>&); _Args = {std::array<int, 5ul>&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = std::array<int, 5ul>*]'
test.cpp:13:30:   required from here
/usr/local/include/c++/4.8.2/functional:1697:61: error: no type named 'type' in 'class std::result_of<std::array<int, 5ul>* (*(std::array<int, 5ul>))(std::array<int, 5ul>&)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/local/include/c++/4.8.2/functional:1727:9: error: no type named 'type' in 'class std::result_of<std::array<int, 5ul>* (*(std::array<int, 5ul>))(std::array<int, 5ul>&)>'
         _M_invoke(_Index_tuple<_Indices...>)
         ^
在/usr/local/include/c++/4.8.2/future:38:0中包含的文件中,
来自测试。cpp:1:
/usr/local/include/c++/4.8.2/functional:在“struct std::_Bind_simple”的实例化中:
/usr/local/include/c++/4.8.2/future:1525:70:std::future std::async(std::launch,_-Fn&&&,_-Args&&……[with _-Fn=std::array*(&)(std::array&);_-Args={std::array&};typename std::result_of::type=std::array*]
/usr/local/include/c++/4.8.2/future:1541:36:std::future std::async(_Fn&&,_Args&&…[带_Fn=std::array*(&)(std::array&);_Args={std::array&};typename std::result_of::type=std::array*]
测试。cpp:13:30:从这里开始需要
/usr/local/include/c++/4.8.2/functional:1697:61:错误:在“class std::result_of”中没有名为“type”的类型
typedef typename result_of::type result_type;
^
/usr/local/include/c++/4.8.2/functional:1727:9:错误:在“class std::result_of”中没有名为“type”的类型
_M_invoke(_Index_tuple)
^
这似乎是libstdc++的问题

因此,我的问题是: 1-GCC是否应该拒绝此代码,或者标准中是否有我不知道的内容。 2-断言是否失败?预期的行为是,采用相同引用的异步函数应该引用相同的对象,但副本似乎是异步任务的本地副本

我尝试过使用clang进行编译,但它与4.8.2有相同的编译错误问题(因为它共享相同的libstdc++),并且它无法编译4.6.3库头

  • 是的,gcc应该拒绝此代码
    std::async
    复制参数并将其作为右值转发。无法将右值绑定到左值引用,因此此操作失败。如果要通过引用传递,请使用
    std::ref(foo)
    。在此特定示例中,对
    std::async(bar,foo)
    的调用基本上执行以下操作:

    template<typename F>
    future<foo_t*> async(F& func,foo_t& arg){
        F func_copy(func);
        foo_t arg_copy(arg);
        // on background thread
        internal_set_future_result(func_copy(std::move(arg_copy)));
        return ...;
    }
    
    模板
    未来异步(F&func、foo\u t&arg){
    F本票副本(本票);
    foo_t arg_copy(arg);
    //关于背景线程
    内部设置未来结果(函数复制(标准::移动(参数复制));
    返回。。。;
    }
    
  • 如果使用
    std::ref(foo)
    ,则断言不应失败。如果代码没有编译,那就没有意义了


  • 请对这些部分添加更多解释:“std::async复制参数”和“不能将右值绑定到左值引用”。我相信你是对的,但是这个答案,就像现在这样,让我困惑。谢谢。这似乎是一个非常罕见的C++例子,它比你更了解…有人会认为他们会使用完美的转发,并假设用户知道他们在做什么。无论如何,编译错误是相当迟钝的。谢谢你的澄清。
    template<typename F>
    future<foo_t*> async(F& func,foo_t& arg){
        F func_copy(func);
        foo_t arg_copy(arg);
        // on background thread
        internal_set_future_result(func_copy(std::move(arg_copy)));
        return ...;
    }