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

如何在C++ JSONDUMP宏中仅通过名称引用调用成员函数?

解决方案:结合C++编译时特性实现统一的字段/方法序列化

纯预处理器没法区分成员变量和成员函数,得结合C++的模板重载或者编译时判断来实现你要的效果,下面给两种可行的方案:

方案一:C++11兼容的模板重载法

这个方法靠重载辅助函数,自动适配成员变量和无参const成员函数:

1. 定义辅助函数和宏

#include <utility>

// 处理成员变量的重载
template<typename T, typename Class>
auto dump_helper(const Class* obj, T Class::*member) -> decltype(obj->*member) {
    return obj->*member;
}

// 处理无参const成员函数的重载
template<typename Ret, typename Class>
auto dump_helper(const Class* obj, Ret (Class::*func)() const) -> Ret {
    return (obj->*func)();
}

// 封装成字段宏
#define JSON_FIELD(name) #name, dump_helper(this, &decltype(*this)::name)

// 你的JSONDUMP宏改造
#define JSONDUMP(...) \
JSONObject jsonDump() const { \
    return JSONObject{ __VA_ARGS__ }; \
}

2. 使用示例

class MyClass {
private:
    int m_size;
    int len() const { return m_size * 2; }
public:
    JSONDUMP(
        JSON_FIELD(m_size),  // 成员变量直接用名称
        JSON_FIELD(len)      // 成员函数也直接用名称,无需加()
    );
};

工作原理:JSON_FIELD(name)会把名称转换成类成员的指针(&MyClass::name),然后根据这个指针是成员变量指针还是成员函数指针,匹配对应的dump_helper重载,自动完成取值或调用。

方案二:C++17的if constexpr简洁法

如果你的项目可以用C++17,用编译时判断会更简洁,不需要写多个重载:

1. 定义宏

#include <type_traits>

#define JSONDUMP(...) \
JSONObject jsonDump() const { \
    auto get_value = [this](auto mem) { \
        // 编译时判断:如果是可调用的成员函数,就调用;否则取成员变量
        if constexpr (std::is_invocable_r_v<decltype((this->*mem)()), const decltype(*this)&>) {
            return (this->*mem)();
        } else {
            return this->*mem;
        }
    }; \
    return JSONObject{ __VA_ARGS__ }; \
}

#define JSON_FIELD(name) #name, get_value(&decltype(*this)::name)

2. 使用方式和方案一完全相同

这个方法靠if constexpr在编译时分支处理,代码更紧凑,可读性更好。

注意事项

  • 这两个方案都只支持无参的const成员函数,如果要支持带参数的函数或者非const函数,需要扩展对应的重载/判断逻辑。
  • 纯预处理器无法实现这个需求,因为预处理器只做文本替换,不知道符号的类型信息,必须依赖C++的编译时类型检查能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:46:18