自定义fmt::formatter处理非const参数的编译链接错误解决
问题:fmt格式化非const引用对象时出现链接错误
你定义了如下类和fmt格式化器:
class MyClass{ public: std::string _cachedString; std::string_view get_string(){ _cachedString = "abc"; return _cachedString; } }; template<> class fmt::formatter<MyClass>{ public: template<typename ParseContext> constexpr auto parse(ParseContext& ctx){return ctx.begin();} template <typename FormatContext> constexpr auto format( MyClass& t, FormatContext& ctx){ return format_to(ctx.out(), "({})", t.get_string()); } };
编译时触发链接错误:
undefined reference to `fmt::v8::detail::value<fmt::v8::basic_format_context<fmt::v8::appender, char> >::value(fmt::v8::detail::unformattable_const)'
问题根源是fmt库默认会尝试以const MyClass&类型匹配格式化器,但你的format函数仅接受非const的MyClass&,导致找不到对应的格式化重载,进而触发未定义符号错误。
解决方案
1. 同时提供const与非const版本的format函数
如果你的类需要同时支持const场景和可修改场景,直接重载format函数即可:
template<> class fmt::formatter<MyClass>{ public: template<typename ParseContext> constexpr auto parse(ParseContext& ctx){return ctx.begin();} // 处理非const对象,允许修改内部状态 template <typename FormatContext> auto format(MyClass& t, FormatContext& ctx){ return format_to(ctx.out(), "({})", t.get_string()); } // 处理const对象的格式化逻辑(按需实现) template <typename FormatContext> auto format(const MyClass& t, FormatContext& ctx){ return format_to(ctx.out(), "({})", t._cachedString); } };
2. 显式指定非const引用格式化
如果只需要格式化非const对象,调用fmt::format时确保传递的是非const引用,同时保证格式化器的签名能被正确匹配。注意检查fmt版本兼容性,确保自定义格式化器的写法符合当前版本要求。
3. 拆分修改与格式化逻辑
若允许调整流程,可以先调用修改对象的方法,再用const引用进行格式化:
MyClass obj; obj.get_string(); // 先完成对象修改 fmt::format("{}", static_cast<const MyClass&>(obj)); // 使用const引用格式化
内容的提问来源于stack exchange,提问作者Aditya Agarwal
相关产品推荐
相关产品推荐

