自定义fmt格式化器中嵌套动态参数的使用与实现问题
自定义fmt格式化器中嵌套动态参数的使用与实现问题
看起来你正在为自定义类型foo_type编写fmt格式化器,而且已经着手处理嵌套格式参数的解析逻辑了对吧?先看看你给出的这段示例代码:
Considering the following working example:
#include<string> #include<fmt/format.h> class foo_type{}; template<> struct fmt::formatter<foo_type>{ private: std::string fmt_; public: auto constexpr inline parse(fmt::format_parse_context& ctx)->fmt::format_parse_context::iterator{ auto it{ctx.begin()}; for(unsigned depth{0}; it != ctx.end(); ++it){ if(*it == '{') ++depth;
从你写的parse方法片段能看出来,你已经意识到要通过跟踪括号的嵌套深度来处理内部的动态参数——这可是实现嵌套格式支持的核心步骤。接下来你只需要补充对应的闭合括号处理逻辑,就能正确提取出当前格式化器对应的格式字符串,同时保留内部的嵌套参数供后续格式化使用。
比如,你可以这样补全parse方法:
if(*it == '}') { // 深度为0时,说明找到了当前格式化器的闭合括号 if(depth == 0) break; --depth; } // 收集格式字符串内容,跳过最外层的{} if(depth > 0 || (*it != '{' && *it != '}')) { fmt_.push_back(*it); } } // 返回跳过闭合括号后的迭代器,让fmt继续处理后续内容 return ++it; } // 再实现format方法,用保存的fmt_来完成自定义格式化 template<typename FormatContext> auto format(const foo_type& foo, FormatContext& ctx) const -> decltype(ctx.out()) { // 这里可以根据fmt_的内容来格式化foo的内部成员,比如假设foo有个int成员value // return fmt::format_to(ctx.out(), fmt_, foo.value); // 先给个简单示例 return fmt::format_to(ctx.out(), "foo_type instance [fmt: {}]", fmt_); } };
这样实现后,你的格式化器就能正确处理嵌套的格式参数了。比如当你写fmt::format("{:{{:>5}}}", foo_instance)时,外层格式化器会把内部的:>5作为自己的格式字符串保存到fmt_里,在format阶段就可以用这个格式来处理具体的内容。
另外要注意,因为你把parse声明为constexpr,所以里面的操作都得符合编译期计算的要求,上面补全的逻辑是满足这个条件的。
备注:内容来源于stack exchange,提问作者kmft3kte
相关产品推荐
相关产品推荐

