std::async 使用绑定到 lambda 的右值引用
std::async using an rvalue reference bound to a lambda
我正在尝试使用 std::bind
将右值引用绑定到 lambda,但是当我将其放入 std::async
调用时遇到问题:(source)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, std::string{"hello world"});
auto future = std::async(bound); // Compiler error here
future.get()
这会发出一个编译器错误,我不太确定如何解释:
error: no type named 'type' in 'class std::result_of(std::basic_string)>&()>'
这是怎么回事?有趣的是,稍作修改就可以按预期编译和工作。如果我将 std::string{"hello world"}
更改为 C 字符串文字,一切正常:(source)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, "hello world");
auto future = std::async(bound);
future.get(); // Prints "hello world" as expected
为什么这个有效但第一个示例无效?
std::bind
将复制 std::string
参数并将其传递给 lambda。但这无法编译,因为 lambda 需要一个右值参数,而 bind
传递给它的将是一个左值。如果你得到 bind
到 move
参数,你可以让它工作,但这需要非常丑陋的转换来消除歧义(因为 std::move
是一个重载函数)。
auto bound = std::bind(lambda, std::bind(static_cast<std::string&&(*)(std::string&)>(std::move),
std::string{"hello world"}));
当然,您可以编写自己的未重载的 move
版本,并避免强制转换。
第二种情况有效,因为当 bind
将 char const *
传递给 lambda 时,会隐式创建一个右值 std::string
临时值。
为了解释您看到的错误消息,在 std::async
的内部某处,正在调用 std::result_of
以确定函数调用表达式的 return 类型。但是,由于上述原因导致该调用表达式无效,因此 result_of
被 SFINAE 淘汰(这是 C++14 的更改)。因此错误 error: no type named 'type' in 'class std::result_of<...>'
.
我正在尝试使用 std::bind
将右值引用绑定到 lambda,但是当我将其放入 std::async
调用时遇到问题:(source)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, std::string{"hello world"});
auto future = std::async(bound); // Compiler error here
future.get()
这会发出一个编译器错误,我不太确定如何解释:
error: no type named 'type' in 'class std::result_of(std::basic_string)>&()>'
这是怎么回事?有趣的是,稍作修改就可以按预期编译和工作。如果我将 std::string{"hello world"}
更改为 C 字符串文字,一切正常:(source)
auto lambda = [] (std::string&& message) {
std::cout << message << std::endl;
};
auto bound = std::bind(lambda, "hello world");
auto future = std::async(bound);
future.get(); // Prints "hello world" as expected
为什么这个有效但第一个示例无效?
std::bind
将复制 std::string
参数并将其传递给 lambda。但这无法编译,因为 lambda 需要一个右值参数,而 bind
传递给它的将是一个左值。如果你得到 bind
到 move
参数,你可以让它工作,但这需要非常丑陋的转换来消除歧义(因为 std::move
是一个重载函数)。
auto bound = std::bind(lambda, std::bind(static_cast<std::string&&(*)(std::string&)>(std::move),
std::string{"hello world"}));
当然,您可以编写自己的未重载的 move
版本,并避免强制转换。
第二种情况有效,因为当 bind
将 char const *
传递给 lambda 时,会隐式创建一个右值 std::string
临时值。
为了解释您看到的错误消息,在 std::async
的内部某处,正在调用 std::result_of
以确定函数调用表达式的 return 类型。但是,由于上述原因导致该调用表达式无效,因此 result_of
被 SFINAE 淘汰(这是 C++14 的更改)。因此错误 error: no type named 'type' in 'class std::result_of<...>'
.