C++获取重载成员函数指针的常用方法

标签 c++

获取重载成员函数(真实成员和具有替代调用约定的静态成员)地址的常用方法是什么?
以下示例在替代调用约定的情况下失败:

#include <iostream>


using namespace std;


struct A {
    int mem(int a) {
        return a * 2;
    };
    int mem(int a, int b) {
        return a + b;
    }
    static int stat(int a) {
        return a * 2;
    }
    static int stat(int a, int b) {
        return a + b;
    }
};


int main() {
    A a;

    cout << "a.mem(1) -> " << a.mem(1) << endl;
    cout << "a.mem(1, 2) -> " << a.mem(1, 2) << endl;
    cout << "A::stat(1) -> " << A::stat(1) << endl;
    cout << "A::stat(1, 2) -> " << A::stat(1, 2) << endl;
    cout << "a.stat(1) -> " << a.stat(1) << endl;
    cout << "a.stat(1, 2) -> " << a.stat(1, 2) << endl;

    cout << "----------------------------------" << endl;

    auto aMem1 = static_cast<int(A::*)(int)>(&A::mem);
    cout << "a.*aMem1(1) -> " << (a.*aMem1)(1) << endl;
    auto aMem2 = static_cast<int(A::*)(int, int)>(&A::mem);
    cout << "a.*aMem2(1, 2) -> " << (a.*aMem2)(1, 2) << endl;
    auto stat1 = static_cast<int(*)(int)>(&A::stat);
    cout << "stat1(1) -> " << stat1(1) << endl;
    auto stat2 = static_cast<int(*)(int, int)>(&A::stat);
    cout << "stat2(1, 2) -> " << stat2(1, 2) << endl;
    // these fail:
    auto aStat1 = static_cast<int(A::*)(int)>(&A::stat);
    cout << "a.*aStat1(1) -> " << (a.*aStat1)(1) << endl;
    auto aStat2 = static_cast<int(A::*)(int, int)>(&A::stat);
    cout << "a.*aStat2(1, 2) -> " << (a.*aStat2)(1, 2) << endl;

    return 0;
}

参见 live示例。

背景:
我不知道实现是使用成员函数还是静态成员函数,因此,我需要一种通用的方法来处理这两者。如上所示,显而易见的方法并不成功。

最佳答案

如果您需要能够以相同的方式处理表达式 &A::x 而不管 x 的静态成员还是非静态成员>A (并且它可能被重载)然后你需要通过一些其他可以接受 R(C::*)(Ts...)R(C::*)(Ts...)constR(*)(Ts...) 并相应地调度。像这样:

template <typename... Ts>
struct UniformResolver {
    template <typename C, typename R>
    constexpr auto operator()(R (C::*func)(Ts...)) const { return resolveMember(func); }
    template <typename C, typename R>
    constexpr auto operator()(R (C::*func)(Ts...) const) const { return resolveMember(func); }
    template <typename R>
    constexpr auto operator()(R (*func)(Ts...)) const { return resolveStatic(func); }
private:
    template <typename F>
    constexpr auto resolveMember(F func) const {
        return [func](auto&&... args) {
            return std::invoke(func, std::forward<decltype(args)>(args)...);
        };
    }
    template <typename F>
    constexpr auto resolveStatic(F func) const {
        return [func](auto&&, auto&&... args) {
            return std::invoke(func, std::forward<decltype(args)>(args)...);
        };
    }
};
template <typename... Ts>
constexpr UniformResolver<Ts...> uresolve {};

这为您提供了一个可调用对象模板 uresolve,它可以调整您的函数指针,返回一个可以以统一方式调用并委托(delegate)给您的函数指针的可调用对象。这就是您将如何使用它:

struct A {
    int mem(int a) const { return a * 2; }
    int mem(int a, int b) const { return a + b; }
    static int stat(int a) { return a * 2; }
    static int stat(int a, int b) { return a + b; }
};

int main() {
    A a;
    auto mem1 = uresolve<int>(&A::mem);
    auto mem2 = uresolve<int, int>(&A::mem);
    auto stat1 = uresolve<int>(&A::stat);
    auto stat2 = uresolve<int, int>(&A::stat);

    std::cout << mem1(a, 1) << '\n';
    std::cout << mem2(a, 1, 2) << '\n';
    std::cout << stat1(a, 1) << '\n';
    std::cout << stat2(a, 1, 2) << '\n';
}

Live demo

关于C++获取重载成员函数指针的常用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54970194/

相关文章:

c++ - 如何管理将指向数组的指针传递给函数

c++ - deleteLater() 在 qt 中是如何工作的?

c++ - 具有多个对象回调的游戏循环 - 第二个对象没有任何反应

c++ - 运行修改后的 litecoin chainparams.cpp 时遇到 "ReadBlockFromDisk: Errors in block header at CBlockDiskPos(nFile=0, nPos=8)"错误

c++ - 带phong阴影和光线追踪的伪像

c++ - C++ 中的对象实例化是否存在显着的固有成本?

c++ - 需要帮助了解递归前缀计算器

c++ - 这个构造函数做什么?

C++编译时断言BASE是EXTENDED的基类并且具有相同的内存地址

c++ - Qt 运行时错误