首页 > 解决方案 > 为什么 std::function 不参与重载决议?

问题描述

我知道下面的代码不会编译。

void baz(int i) { }
void baz() {  }


class Bar
{
    std::function<void()> bazFn;
public:
    Bar(std::function<void()> fun = baz) : bazFn(fun){}

};

int main(int argc, char **argv)
{
    Bar b;
    return 0;
}

因为std::function据说不考虑重载解决方案,正如我在另一篇文章中所读到的那样。

我不完全理解迫使这种解决方案的技术限制。

我在 cppreference 上阅读了关于翻译模板的阶段,但我想不出任何我找不到反例的推理。向半门外汉(对 C++ 还是新手)解释,是什么以及在哪个翻译阶段导致上述编译失败?

标签: c++templatestranslationstd-function

解决方案


这与“翻译阶段”没有任何关系。这纯粹是关于std::function.

看,std::function<R(Args)>不要求给定的函数完全是 type R(Args)。特别是,它不需要给它一个函数指针。它可以采用任何可调用类型(成员函数指针,一些具有 重载的对象operator()),只要它是可调用的,就好像它接受Args参数并返回可转换为的 R东西(或者如果Rvoid,它可以返回任何东西)。

为此,适当的构造函数std::function必须是模板template<typename F> function(F f);。也就是说,它可以采用任何函数类型(受上述限制)。

该表达式baz表示一个重载集。如果您使用该表达式来调用重载集,那很好。如果将该表达式用作采用特定函数指针的函数的参数,C++ 可以将重载集缩减为单个调用,从而使其正常。

但是,一旦函数是模板,并且您使用模板参数推导来确定该参数是什么,C++ 就不再能够确定重载集中正确的重载是什么。所以你必须直接指定它。


推荐阅读