如何仅用fmt库实现逗号分隔的tuple打印?
使用fmt库实现Tuple的格式化输出
针对需求——替代ostream实现,用fmt库完成tuple的(元素1, 元素2, ...)格式输出,以下提供两种可行方案:
方案一:直接封装格式化函数
无需特化formatter,借助fmt::join和折叠表达式快速实现,代码简洁高效:
#include <fmt/core.h> #include <tuple> #include <utility> template <typename TupleT, std::size_t... Is> std::string format_tuple_impl(const TupleT& tp, std::index_sequence<Is...>) { return fmt::format("({})", fmt::join(std::make_tuple(std::get<Is>(tp)...), ", ")); } template <typename TupleT, std::size_t TupSize = std::tuple_size_v<TupleT>> std::string format_tuple(const TupleT& tp) { return format_tuple_impl(tp, std::make_index_sequence<TupSize>{}); } int main() { std::tuple tp{10, 20, "hello"}; fmt::print("{}", format_tuple(tp)); // 输出:(10, 20, hello) }
fmt::join会自动处理元素间的逗号分隔,无需手动判断索引,代码可读性和效率都有保障。
方案二:特化fmt::formatter实现原生支持
如果想让tuple直接兼容fmt::print("{}", tp)的写法,需要特化fmt::formatter模板:
#include <fmt/core.h> #include <tuple> #include <utility> namespace fmt { template <typename... Args> struct formatter<std::tuple<Args...>> { // 解析格式说明符(此处简化,不处理自定义格式) template <typename ParseContext> constexpr auto parse(ParseContext& ctx) { return ctx.begin(); } // 执行格式化逻辑 template <typename FormatContext> auto format(const std::tuple<Args...>& tp, FormatContext& ctx) { auto out = ctx.out(); *out++ = '('; size_t index = 0; // 折叠表达式遍历所有元素,插入分隔符并格式化 ((index++ > 0 ? (out = fmt::format_to(out, ", "), true) : true), (out = fmt::format_to(out, "{}", std::get<index-1>(tp))), ...); *out++ = ')'; return out; } }; } // namespace fmt int main() { std::tuple tp{10, 20, "hello"}; fmt::print("{}", tp); // 直接输出:(10, 20, hello) }
扩展说明
如果需要支持对tuple元素的自定义格式(比如浮点数保留小数),可以修改parse方法存储格式说明符,在format时传递给每个元素的格式化逻辑。两种方案都利用了折叠表达式,编译器会做高效优化,性能与原ostream版本相当。
内容的提问来源于stack exchange,提问作者Swift - Friday Pie
相关产品推荐
相关产品推荐

