编译以下代码时,Visual Studio会报告:
\main.cpp(21): error C2664: 'std::_Call_wrapper<std::_Callable_pmd<int ClassA::* const ,_Arg0,false>,false> std::mem_fn<void,ClassA>(int ClassA::* const )' : cannot convert argument 1 from 'overloaded-function' to 'int ClassA::* const '
1> with
1> [
1> _Arg0=ClassA
1> ]
1> Context does not allow for disambiguation of overloaded function
为什么在创建mem_fptr1
时编译器会感到困惑?但是当我指定类型时,有些mem_fptr2
是可以的。
我可以创建一个不带参数的重载成员函数的成员函数指针吗?
class ClassA
{
public:
void memberfunction()
{
std::cout <<"Invoking ClassA::memberfunction without argument" << std::endl;
}
void memberfunction(int arg)
{
std::cout << "Invoking ClassA::memberfunction with integer " << arg << std::endl;
}
};
int main()
{
auto mem_fptr1 = std::mem_fn<void, ClassA>(&ClassA::memberfunction);
auto mem_fptr2 = std::mem_fn<void, ClassA, int>(&ClassA::memberfunction);
mem_fptr1(ClassA());
mem_fptr2(ClassA(), 3);
}
答案 0 :(得分:11)
template overloads taking a variadic list of argument types是在C ++ 11中引入的,但在C ++ 14中被移除为defect #2048。指定特定重载的方法是将函数类型指定为第一个模板参数(第二个模板参数,类类型,可以省略,因为它可以推导出来):
auto mem_fptr1 = std::mem_fn<void()>(&ClassA::memberfunction);
auto mem_fptr2 = std::mem_fn<void(int)>(&ClassA::memberfunction);
然后,函数类型R
由类T
组成R T::*
,以提供成员函数类型。这也允许在数据成员中形成std::mem_fn
(其中R
是非函数类型)。
请注意,您的代码(对于mem_fptr2
)在C ++ 14中不起作用,其中模板重载会删除参数类型的可变参数列表;上述代码适用于标准的两个版本。
另一种方法是执行成员函数转换;在这种情况下,您不需要为mem_fn
指定模板参数:
auto mem_fptr1 = std::mem_fn(
static_cast<void (ClassA::*)()>(&ClassA::memberfunction));
auto mem_fptr2 = std::mem_fn(
static_cast<void (ClassA::*)(int)>(&ClassA::memberfunction));