如何使用{fmt}库为std::string/std::string_view类型数据生成带引号的输出?
解决{fmt}库中std::string/std::string_view自动带引号格式化的问题
嘿,这个需求刚好可以用{fmt}的自定义格式化器特化来实现,完美适配你开发库时处理未知类型的场景!
核心思路
我们只需要为std::string和std::string_view类型特化fmt::formatter结构体,让它们在格式化时自动包裹双引号,其他类型保持默认行为即可。
实现代码
#include <fmt/format.h> #include <string> #include <string_view> // 为std::string特化格式化器(复用string_view的实现) template <> struct fmt::formatter<std::string> : fmt::formatter<std::string_view> {}; // 为std::string_view特化格式化器,实现带引号输出 template <> struct fmt::formatter<std::string_view> { template <typename FormatContext> auto format(std::string_view s, FormatContext& ctx) { // 将字符串用双引号包裹后输出 return fmt::format_to(ctx.out(), "\"{}\"", s); } };
测试效果
用你提供的示例代码测试:
int main() { fmt::print("Hello {}!", "Terens"); // 输出:Hello "Terens"! return 0; }
其他类型的格式化不受影响,比如:
fmt::print("Age: {}, Score: {}\n", 25, 98.5); // 输出:Age: 25, Score: 98.5 fmt::print("String view: {}\n", std::string_view("example")); // 输出:String view: "example"
可选扩展:灵活控制引号(按需)
如果你的库需要偶尔输出不带引号的字符串,可以给格式化器添加格式选项解析,比如用:n表示不需要引号:
template <> struct fmt::formatter<std::string_view> { bool quoted = true; // 解析格式标志,支持`:n`关闭引号 template <typename ParseContext> constexpr auto parse(ParseContext& ctx) { auto it = ctx.begin(); if (it != ctx.end() && *it == 'n') { quoted = false; ++it; } return it; } template <typename FormatContext> auto format(std::string_view s, FormatContext& ctx) { if (quoted) { return fmt::format_to(ctx.out(), "\"{}\"", s); } else { return fmt::format_to(ctx.out(), "{}", s); } } };
使用方式:
std::string name = "Terens"; fmt::print("带引号:{}\n", name); // 输出:带引号:"Terens" fmt::print("不带引号:{:n}\n", name); // 输出:不带引号:Terens
这种方式完全符合你开发库的需求:不需要修改现有格式化字符串,自动识别类型应用带引号格式,同时保持其他类型的正常输出。
内容的提问来源于stack exchange,提问作者Terens Tare
相关产品推荐
相关产品推荐

