c++ - std::async 使用绑定(bind)到 lambda 的右值引用

标签 c++ c++11 lambda stdbind

我正在尝试使用 std::bind 将右值引用绑定(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"}));

Live demo

当然,您可以编写自己的 move 版本没有重载,并避免这种转换。

第二种情况有效,因为当bind通过 char const *对于 lambda,一个右值 std::string临时是隐式创建的。


为了解释您看到的错误消息,在 std::async 的内部某处, std::result_of被调用以确定函数调用表达式的返回类型。但是,由于上述原因导致该调用表达式无效, result_of 正在被 SFINAE 淘汰(这是 C++14 的更改)。因此错误 error: no type named 'type' in 'class std::result_of<...>' .

关于c++ - std::async 使用绑定(bind)到 lambda 的右值引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30084357/

相关文章:

c++ - "placement new"有什么用?

c++ - boost::unordered_set of char16_t 字符串

python - 如何忽略无效输入或在排序函数中添加 try except 代码?

python - Python lambda 函数中的 float 恒等比较

c++ - 如何在 C++ 中从文件定义数据类型?

c++ - std::bind 不会接受绑定(bind)占位符的 std::cref - 为什么?

android - 在android中为cCURL添加ssl证书有错误

c++ - std::packaged_task 没有违反销毁 promise ?

c++ - 如何使用 sfinae 选择构造函数?

python - Pandas groupby 与 lambda 并在列表中