1. std::format基础与本地化支持
C++20引入的std::format彻底改变了字符串格式化的游戏规则。与传统的printf或iostream相比,它提供了类型安全、编译时检查以及更直观的语法。但很多人不知道的是,std::format还内置了对本地化(locale)的完整支持。
1.1 基本格式化语法
std::format的核心语法非常直观:
cpp复制std::string result = std::format("Hello, {}!", "World"); // 输出: Hello, World!
这里的{}是占位符,会自动按顺序匹配参数。更复杂的格式控制可以通过冒号指定:
cpp复制std::format("{:.2f}", 3.14159); // 输出: 3.14
1.2 本地化字符串输出
std::format的本地化支持通过locale参数实现。考虑货币格式化的例子:
cpp复制#include <locale>
#include <format>
double price = 1234.56;
std::cout << std::format("Price: {:L}\n", price); // 默认locale
std::cout << std::format(std::locale("en_US.UTF-8"), "Price: {:L}\n", price);
// 输出可能为: Price: $1,234.56
关键点在于L格式修饰符,它指示使用当前locale的约定进行格式化。对于数字、日期、货币等类型,本地化输出特别有用。
1.3 编译时格式检查
从C++20 P2216R3开始,std::format会在编译时检查格式字符串的有效性:
cpp复制std::format("{:.2f}", "text"); // 编译错误!字符串不能使用浮点格式
这种编译时检查通过std::format_string类型实现,大大减少了运行时错误。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 自定义格式化器实现
当我们需要格式化自定义类型时,必须特化std::formatter模板。这是std::format最强大的特性之一。
2.1 基本formatter特化
假设我们有一个简单的Point类型:
cpp复制struct Point {
double x, y;
};
为其实现formatter:
cpp复制#include <format>
template <>
struct std::formatter<Point> {
// 解析格式说明(如"{:.2f}"中的".2f")
constexpr auto parse(std::format_parse_context& ctx) {
return ctx.begin(); // 本例中
