liz*_*isk 21 c++ multithreading asynchronous c++11
我注意到,将非const引用作为参数传递给它是不可能的std::async.
#include <functional>
#include <future>
void foo(int& value) {}
int main() {
int value = 23;
std::async(foo, value);
}
Run Code Online (Sandbox Code Playgroud)
我的编译器(GCC 4.8.1)为此示例提供了以下错误:
error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’
Run Code Online (Sandbox Code Playgroud)
但是,如果我包传递到值std::async的std::reference_wrapper,一切都OK了.我假设这是因为std::async按值获取它的参数,但我仍然不明白错误的原因.
Seb*_*edl 34
这是一个深思熟虑的设计选择/权衡.
首先,不一定能够找出传递给async它的functionoid是否通过引用获取它的参数.(例如,如果它不是一个简单的函数而是一个函数对象,它可能会有一个重载的函数调用操作符.)所以async不能说,"嘿,让我只检查目标函数想要什么,我会做正确的事情".
所以设计问题是,如果可能的话,它是否通过引用获取所有参数(即,如果它们是左值),还是它总是复制?制作副本是一个安全的选择:副本不能成为悬空,副本不能表现出竞争条件(除非它真的很奇怪).这就是所做的选择:默认情况下会复制所有参数.
但是,编写该机制使得它实际上无法将参数传递给非const左值引用参数.这是安全性的另一个选择:否则,您希望修改原始左值的功能会修改副本,从而导致很难追踪的错误.
但是,如果你真的,真的想要非const左值参考参数怎么办?如果您承诺留意悬挂参考和竞争条件,该怎么办?这就是std :: ref的用途.它是对危险引用语义的明确选择.这是你的说法,"我知道我在这里做什么."
Pet*_*ker 20
std::async(以及其他完美转发的函数)查看您传递的参数类型,以确定要执行的操作.他们没有看到最终如何使用这个论点.因此,要通过引用传递对象,您需要告诉std::async您正在使用引用.但是,简单地传递引用将不会这样做.您必须使用通过引用std::ref(value)传递value.
Die*_*ühl 14
问题本身只与以下方面有轻微关系std::async():在定义操作结果时,std::async()使用std::result_of<...>::type其所有参数都是std::decay<...>::type"ed".这是合理的,因为std::async()它采用任意类型并转发它们以将它们存储在某个位置.要存储它们,函数对象和参数都需要值.因此,std::result_of<...>使用类似于此:
typedef std::result_of<void (*(int))(int&)>::type result_type;
Run Code Online (Sandbox Code Playgroud)
...并且由于int不能绑定int&(不是需要绑定int的左值类型int&),这会失败.在这种情况下失败意味着std::result_of<...>没有定义嵌套type.
后续问题可能是:这种用于实例化的类型是什么std::result_of<...>?我们的想法是ResultType(ArgumentTypes...)滥用函数调用语法:不是结果类型,而是传递函数类型,并std::result_of<...>确定调用该函数类型时调用的函数类型,并调用给定的参数列表.对于函数指针类型,它实际上并不那么有趣,但函数类型也可以是需要考虑重载的函数对象.基本上,std::result_of<...>就像这样使用:
typedef void (*function_type)(int&);
typedef std::result_of<function_type(int)>::type result_type; // fails
typedef std::result_of<function_type(std::reference_wrapper<int>)>::type result_type; //OK
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9361 次 |
| 最近记录: |