带有重载成员函数的C++std::mem_fn

C++ std::mem_fn with overloaded member function

本文关键字:mem fn C++std 重载 成员 函数      更新时间:2023-10-16

编译以下代码时,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);
}

采用参数类型的可变列表的模板重载在C++11中引入,但在C++14中作为缺陷#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中不起作用,因为在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));