2

请考虑以下示例:

#include <iostream>
#include <future>

std::size_t calc_something(std::size_t lim_)
{   
    std::size_t result = lim_ * 10;
    return result;
}

void calc_something(std::size_t lim_, std::promise<std::size_t> &promise_)
{   
    std::size_t result = lim_ * 10;
    promise_.set_value(result);
}

void async_calc()
{
    std::future<std::size_t> async_calc = std::async(calc_something, 5);
    std::cout<< "async_calc = " << async_calc.get() <<std::endl;
}

我对多线程仍然很陌生,但是为什么 - 在地球上 - 不能std::async选择正确的重载?第二个重载使用对std::promise对象的引用。

我在这里看过这个问题,但没有解释为什么。此外,我没有收到歧义错误。

我得到的错误是:

error: no matching function for call to 'async' std::future<std::size_t> async_calc = std::async(calc_something, 5);
4

3 回答 3

4

重载解决基于调用站点指定的参数类型。当您调用 时std::async,您不是在调用,calc_something而是将指向函数的指针传递给std::async. 没有calc_something调用参数,也没有办法解决两个重载地址中的哪一个要传递给std::async.

编译器不能使用 的后续参数std::async来解决重载。从编译器的角度来看,所有std::async参数都是不相关的,并且没有任何暗示它们将用于调用calc_something. 实际上,您可以使用与接受std::async类型不同的参数进行调用calc_something,并且它会起作用,因为它们会在calc_something被调用时被转换。

为了解决这种歧义,您必须将指针显式转换calc_something为函数指针的确切类型,以匹配其中一个重载。

std::async((std::size_t (*)(std::size_t))calc_something, 5);
于 2020-02-03T15:12:07.340 回答
3

重载集不能按原样作为参数发送,必须先转换为函数指针,或者必须提升为对象。

重载集必须转换,因为只有函数的名称表示完整的函数集,但您必须只发送其中一个。编译器如何选择正确的取决于您发送给它的参数。调用它提供了参数的类型,但转换为函数指针也为编译器提供了关于必须发送哪个重载的足够信息。

转换为函数指针通常是最简单的方法:

auto function = static_cast<std::size_t(*)(std::size_t)>(calc_something);
std::future<std::size_t> async_calc = std::async(function, 5);

提升是使用 lambda 完成的:

std::future<std::size_t> async_calc = std::async([](auto lim) { return calc_something(lim); }, 5);

由于您调用了重载集,因此可以在此处提升,因此编译器可以选择一个参数。

它只是不能延迟重载集的决定,但对于 lambda 和模板函数它可以。

于 2020-02-03T15:09:04.253 回答
2

std::async()是一个函数模板,您将calc_something其作为参数传递给它。calc_something但是,由于重载,有两个函数被调用。必须在' 参数的calc_something()模板推导发生之前选择重载。std::async()

std::future<std::size_t> async_calc = std::async(calc_something, 5);

在上面的代码中,哪个重载将被传递给std::async()

std::size_t calc_something(std::size_t);
void calc_something(std::size_t, std::promise<std::size_t> &);

您必须指定:

std::async(static_cast<std::size_t(*)(std::size_t)>(calc_something), 5);
于 2020-02-03T15:09:29.780 回答