为什么重载函数的函数指针需要static_cast?

Why function pointer of overloaded function need static_cast?

对于下面的代码,我得到了错误

#include <iostream>
#include <functional>

using namespace std;

class A {};
class B {};

namespace N
{
    void func(A a, int z){}
    void func(B a, int z){}
}

void func_1(std::function<void(A, int)> x)
{
    A a;
    x(a, 1);
}

int main()
{
    func_1(N::func);
    
    return 0;
}

错误:

    main.cpp:23:19: error: cannot resolve overloaded function 'func' based on conversion to type 'std::function<void(A, int)>'
   23 |     func_1(N::func);

如果我们将 func_1(N::func); 静态转换为 func_1(static_cast<void (&)(A, int)>(N::func));,那么这个工作正常。但我希望它能在没有演员表的情况下工作。

std::function<void(A, int)>void(*)(A, int).

更复杂
template< class F >
function( F f );

Initializes the target with std::move(f). If f is a null pointer to function or null pointer to member, *this will be empty after the call. This constructor does not participate in overload resolution unless f is Callable for argument types Args... and return type R.

您甚至不知道哪些构造函数参与了重载决议,直到您决定 N::func 您的意思。

人们可以设想一种组合的重载决议和模板参数推导方案,该方案可以通过在(任意多个)构造函数的其他有效实例中尝试 std::function<void(A, int)>::function<void(*)(A, int)> 来“在中间相遇”。

问题比比皆是。

  1. 它必须得到可证明的答案。通常有无限可能的模板实例化。如果你通过了 int g(A, int).
  2. ,你还希望它能够选择 int(*)(A, int)
  3. 它确实应该同意当前的方案,得出明确的答案。
  4. 每个编译器供应商都必须正确实施它。

作为一种方便的解决方法,您可以提供这种 func_1 重载。

...

void func_1(void(*x)(A, int))
{
    func_1(std::function<void(A, int)>{x});
}

现在它可以在没有 static_cast 的情况下正常工作:demo