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

C++23中自定义范围格式化的分隔符与括号的理想实现方式及推荐实践

C++23中自定义范围格式化的分隔符与括号的理想实现方式及推荐实践

在C++23里,我们可以直接用std::print/std::println来格式化整个范围,对应的标准提案让这个操作变得非常便捷。比如下面这段代码:

std::vector v = {10, 2, 42, 15};
std::println("{::02X}", v); /* 02X是范围元素的格式说明符 */

它会输出:

[0A, 02, 2A, 0F]

不过如果我们想自定义输出的括号和分隔符——比如把括号换成|,分隔符换成-,得到这样的输出:

|0A-02-2A-0F|

该怎么实现呢?

你可能已经了解到,std::range_formatter提供了set_brackets()和set_separator()这两个自定义接口,所以最直观的做法是特化std::formatter模板,让std::vector的格式化器继承自std::range_formatter,并在构造函数里设置我们需要的样式:

template<class T, class charT>
struct std::formatter<std::vector<T>, charT> : std::range_formatter<T, charT> { 
  constexpr formatter() {
    this->set_brackets("|", "|");
    this->set_separator("-");
  }
};

这样修改后,就能得到我们想要的输出效果了。

不过你可能会好奇:有没有更理想的方式?比如直接通过格式化字符串来指定括号和分隔符?可惜的是,当前C++23标准里还不支持这种写法——没办法像控制元素格式那样,在格式字符串里直接配置范围的括号和分隔符,这算是当前标准的一个小局限。

那当前标准下,推荐的实践方式是什么呢?这里分两种场景来说:

  • 全局统一修改样式:如果你的项目里所有std::vector的格式化都需要统一的自定义样式,那上面的全局特化写法是可行的,它简单直接,符合标准规范。
  • 单次格式化自定义:如果只是某一处需要特殊样式,不想影响全局的默认行为,那更推荐手动创建std::range_formatter对象,设置好样式后再进行格式化,比如:
std::vector v = {10, 2, 42, 15};
auto custom_formatter = std::range_formatter<int>{};
custom_formatter.set_brackets("|", "|");
custom_formatter.set_separator("-");
std::println("{}", std::format_to(std::string{}, custom_formatter, v));

至于你问到的这个解决方案有没有问题?其实刚才的特化写法是完全符合标准要求的,std::range_formatter本身就是设计用来让用户继承并自定义的,所以这个实现是合法且安全的。唯一的遗憾就是当前标准还不支持通过格式化字符串直接配置,不过说不定未来的C++版本会加入这个特性,让范围格式化的自定义更灵活。

备注:内容来源于stack exchange,提问作者康桓瑋

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 10:44:35