问题描述
#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 );
使用
std::move(f)
初始化目标。如果f
是函数的空指针或成员的空指针,则*this
将在调用后为空。除非参数类型为f
的{{1}}是 Callable 并且返回类型为Args...
的,否则该构造函数不参与重载解析。
您甚至都不知道是什么构造函数参与重载解析,直到您确定要表示的R
。
可以构想一种组合的重载解析和模板参数推导方案,该方案可以通过在构造函数的其他(任意多个)有效实例中尝试N::func
来“满足”。
问题很多。
- 必须证明是一个答案。通常,模板有无限可能的实例化。如果您通过
std::function<void(A,int)>::function<void(*)(A,int)>
,您还希望它能够选择int(*)(A,int)
。 - 它确实应该与当前的方案相吻合。
- 每个编译器供应商都必须正确实现它。
作为方便的解决方法,您可以提供这种func_1
重载。
...
void func_1(void(*x)(A,int))
{
func_1(std::function<void(A,int)>{x});
}
现在,它在没有static_cast
的情况下可以正常工作:demo