为什么可以将左值传递给“std::async”,即使它采用右值引用?

Why is it possible to pass an lvalue to `std::async` even though it takes an rvalue reference?

函数std::async定义如下:

template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
    async( Function&& f, Args&&... args );

正如我们所见,它将两个参数都作为右值引用,或者更准确地说,作为“通用引用”(对模板参数类型的右值引用)。

传递一个简单的函数指针(例如 std::async(myfunction))有效,但我不明白为什么。

我的理解是您可以将右值绑定到 const 左值引用 - 但反之则不行。您不能将左值绑定到右值引用(不使用 std::move 将其转换为右值)。

但是 - 在调用 std::async(myfunction) 时,std::async 模板被实例化为 Function = <some_func_type>,因此变为 std::async<some_func_type>(some_func_type&&)。也就是说 - 它需要一个右值引用。然而,我们给它传递了一个左值。

为什么有效?

As we can see, it takes both arguments as rvalue-references, or more precisely, as "universal references" (rvalue references to the template argument types).

术语“通用引用”(或“转发引用”)不是 更精确 右值引用的术语。这是另一回事。

当您将 && 放在这样的模板参数类型上时,它就是转发引用。根据设计,这些将绑定到左值。

tl;dr:不是右值引用。

(好吧,有点像,但是 deduction and reference-collapsing rules make it effectively not one,所以我们不称它为一个。因此这种情况的特殊名称:“转发参考".)