You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++元编程实现类似mem_fn的工具,将成员函数转为C风格函数指针

解决方案

实现思路

通过模板自动萃取类成员函数的返回值、所属类、参数列表,生成符合要求的无捕获lambda作为适配层,无捕获lambda可以直接转换为对应签名的C风格函数指针,无需手动为每个成员函数编写适配代码。

通用适配代码

#include <utility>

// 适配普通非const成员函数
template <typename Ret, typename Class, typename... Args>
constexpr auto make_c_adapter(Ret(Class::*mem_func)(Args...)) {
    // 无捕获lambda可以隐式转换为C函数指针,+号强制触发转换
    return +[](void* data, Args... args) -> Ret {
        Class* instance = static_cast<Class*>(data);
        return (instance->*mem_func)(std::forward<Args>(args)...);
    };
}

// 适配const成员函数,按需增加
template <typename Ret, typename Class, typename... Args>
constexpr auto make_c_adapter(Ret(Class::*mem_func)(Args...) const) {
    return +[](void* data, Args... args) -> Ret {
        const Class* instance = static_cast<const Class*>(data);
        return (instance->*mem_func)(std::forward<Args>(args)...);
    };
}

使用示例

修改原有代码的main函数即可直接使用:

int main() {
    // 原有写法可正常保留
    regisAdd(doAdd);
    callAdd();
    regisAdd([](void* data, int a, int b) {
        return static_cast<ABC*>(data)->add(a, b);
    });
    callAdd();

    // 通用适配写法,无需手动编写适配函数
    regisAdd(make_c_adapter(&ABC::add));
    callAdd();
    regisOther(make_c_adapter(&ABC::other));
    callOther();

    return 0;
}

原理解释

  • 模板会根据传入的成员函数指针自动推导所有类型参数,不需要手动指定模板实参
  • 无捕获lambda前面加+是强制触发lambda到函数指针的转换,保证返回值就是C风格函数指针类型
  • 每个不同的成员函数指针都会实例化独立的模板,对应的lambda也是独立的,不会出现地址冲突
  • 该实现兼容C++11及以上标准,不需要依赖任何第三方库

内容的提问来源于stack exchange,提问作者0xFFFFFFFF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 06:54:05