Rob*_*son 2 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 = std::async(bar, foo);
assert(a.get() == b.get());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC 4.6.3编译时没有任何投诉.但是,这在运行时失败:
test: test.cpp:15: int main(): Assertion `a.get() == b.get()' failed.
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
但是,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...>)
^
Run Code Online (Sandbox Code Playgroud)
这似乎是一个libstdc ++问题.
所以我的问题是:1 - GCC应该拒绝这个代码,还是标准中有一些我不知道的东西.2 - 断言是否应该失败?预期的行为是,采用相同引用的异步函数应该引用同一个对象,但看起来副本是异步任务的本地副本.
我尝试使用clang编译,但它与4.8.2具有相同的编译错误问题(因为它共享相同的libstdc ++),并且它无法编译4.6.3库头.
是的,gcc应拒绝此代码.std::async复制参数并将它们转发为rvalues.您不能将右值绑定到左值引用,因此失败.如果你想通过引用传递使用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 ...;
}
Run Code Online (Sandbox Code Playgroud)如果你使用std::ref(foo)那么断言不应该失败.如果代码没有编译,那么这是一个有争议的问题.