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

为何std::shared_ptr<Example>的隐藏友元to_json/from_json可被nlohmann库识别?

关于nlohmann::json中std::shared_ptr隐藏友元序列化的疑问

我这段代码在GCC和Clang编译器下均可编译运行且符合预期功能,但令我感到意外:由于Example类被封装在std::shared_ptr中,我原本以为必须使用adl_serializer特化才能让nlohmann::json库找到to_json/from_json函数,而非使用隐藏友元实现。因此我的问题是:这是符合预期的行为吗(原因是什么)?还是编译器的bug,未来修复后会导致代码失效?

#include <memory>
#include <nlohmann/json.hpp>

struct Example {
    int a;
    int b;

    Example(int a, int b) : a(a), b(b){};

    Example(Example&&) = delete;
    Example& operator=(Example&&) = delete;
    Example(Example&) = delete;
    Example& operator=(Example&) = delete;

    friend void to_json(nlohmann::json& j, const std::shared_ptr<Example>& p) {
        j = {{"a", p->a}, {"b", p->b}};
    }

    friend void from_json(const nlohmann::json& j,
                          std::shared_ptr<Example>& p) {
        p = std::make_shared<Example>(j.at("a").get<int>(),
                                       j.at("b").get<int>());
    }
};

int main() {
    auto j = R"({ "a" : 1, "b" : 2 })"_json;

    auto c = j.get<std::shared_ptr<Example>>();

    auto j2 = nlohmann::json(c);
}

这是符合预期的行为,核心原因是C++标准中的参数依赖查找(ADL)规则:

  • 当nlohmann::json库尝试解析std::shared_ptr<Example>类型的序列化/反序列化时,会触发ADL查找对应的to_json/from_json函数。ADL会自动搜索与参数类型关联的所有命名空间——这里既包括std(因为std::shared_ptr属于该命名空间),也包括Example所在的全局命名空间。
  • 你在Example类内部定义的友元函数属于隐藏友元,这类函数不会暴露到全局作用域,只能通过ADL被查找。由于Example在全局命名空间,当ADL查找std::shared_ptr<Example>相关的函数时,会匹配到这个友元函数。
  • 这种写法完全遵循C++标准和nlohmann::json库的设计逻辑,并没有依赖编译器bug,未来版本的编译器也不会因为修复问题而导致代码失效。

额外说明:nlohmann::json的序列化机制优先级是ADL查找用户自定义函数 > adl_serializer特化 > 默认实现,所以你的写法完全契合库的设计思路。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:45:42