!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!!
作者:mohist
本文翻译:
水平有限,仅供参考,欢迎指正。 有兴趣的,看看原文。
fmt版本: 7.0.1
--------------------------------------------------------------------------
A、介绍#
fmt库由一下模块组成:
fmt/core.h: 提供参数处理的一系列接口 和 一个轻量级的格式化函数集合。
fmt/format.h: 提供了用于编译时的格式化字符串检查、宽字符、迭代输出 和支持用户子自定义的接口。
fmt/ranges.h: 提供了针对元组和容器ranges的额外的格式化支持
fmt/chrono.h: 提供了时间和日期的格式化处理的接口
fmt/compile.h: 格式化字符串编译
fmt/ostream.h: 标准输出流的支持
fmt/printf.h: printf格式化
fmt库提供的函数和类型都在fmt的命名空间下和加上了前缀 FMT_
注意: fmt格式化都是在大括号 {}内。
B、core api
0、包含头文件:
#include
1、fmt::foroomat返回一个字符串。
std::string message = fmt::format("The answer is {}", 42);
2、fmt::print标准输出, 与 std::cout的输出相仿
#include
fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
3、fmt::print支持写入文件,写入的字符串是用的UNICODE编码。函数原型如下:
template
void fmt::print(std::FILE f, const S &format_str, Args&&... args)
函数的第一个参数是文件指针:
fmt::print(stderr, "Don't {}!", "panic");
4、命名参数:通过指定参数名称的方式来调用参数。方便调用参数时按调用者的需要来排列顺序,而不必死守函数声明时的顺序,同时结合默认参数值的特性,可以选择使用默认参数还是不使用默认参数。 函数原型如下:
template
detail::named_arg fmt::arg(const Char name, const T &arg)
该函数将返回一个用于函数参数的格式化字符串。使用方法:
fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
注意: 命名参数不能在编译的时候检查格式化字符串的错误
5、参数列表 Argument Lists
5.1)、函数原型:
template
format_arg_store fmt::make_format_args(const Args&... args)
构造一个format_arg_store对象,该对象包含对参数的引用,并且可以隐式转换为format_args。可以省略上下文,在这种情况下,它默认为上下文。
有关生命周期的考虑,请参见arg()。
5.2)、class fmt::format_arg_store类
template
class fmt::format_arg_store
引用参数的数组。可以将其隐式转换为basic_format_args,以传递给类型擦除的格式函数,例如vformat()。
fmt::format_arg_store 的公有函数:
5.2.1)、push_back函数原型
template
void push_back(const T &arg)
该函数将参数arg自动添加到自动存储的内存中,以便传递给需要格式化参数的函数。
请注意,如有必要,将自定义类型和字符串类型(但不包括字符串view)复制到存储中,以动态分配内存, 例如:
fmt::dynamic_format_arg_store store;
store.push_back(42);
store.push_back("abc");
store.push_back(1.5f);
std::string result = fmt::vformat("{} and {} and {}", store);
5.2.2)、 push_back函数原型:
template
void push_back(std::reference_wrapper arg)
该函数将参数arg自动添加到自动存储的内存中,以便传递给需要格式化参数的函数。通过std :: ref()/ std :: cref()的引用,支持包装在std :: reference_wrapper中的命名参数。例如:
fmt::dynamic_format_arg_store store;
char str【】 = "1234567890";
store.push_back(std::cref(str));
int a1val{42};
auto a1 = fmt::arg("a1", a1_val);
store.pushback(std::cref(a1));
// Changing str affects the output but only for string and custom types.
str【0】 = 'X';
std::string result = fmt::vformat("{} and {a1}");
assert(result == "X234567890 and 42");
5.2.3)、push_back 函数原型:
template
void push_back(const detail::named_arg &arg)
将命名参数添加到动态存储中,以便以后传递给格式化函数。std::reference_wrapper可以避免参数传递时的拷贝。
5.2.4)、clear原型:
void clear()
该函数将清除存储中的所有参数。
5.2.5)、reserve函数原型:
void reserve(size_t new_cap, size_t new_cap_named)
保留存储空间以至于能容纳new_cap参数,也包括new_cap_named 的命名参数。
5.3)、class fmt::basic_format_args类
template
class fmt::basic_format_args
格式化参数集合的视图。 为了避免生命周期的问题,它仅应在类型擦除的函数中用作参数类型,例如vformat函数:
void vlog(string_view format_str, format_args args); // OK
format_args args = make_format_args(42); // Error: dangling reference
其公有函数:
5.3.1)、basic_format_args重载:
template
basic_format_args(const format_arg_store &store)
从format_arg_store 构造一个 basic_format_args 对象。
5.3.2)、basic_format_args重载:
basic_format_args(const dynamic_format_arg_store &store)
从 dynamic_format_arg_store 构造一个 basic_format_args 对象。
5.3.3)、basic_format_args重载:
basic_format_args(const format_arg args, int count)
根据一组动态参数构造一个basic_format_args对象。
5.4)、format_arg 的get函数原型:
format_arg get(int id) const
返回具有指定ID的参数。
5.5)、结构体 fmt::format_args
fmt::format_args是【basic_format_args】的别名,继承 fmt::basic_format_args
5.6)、类 fmt::basic_format_arg:
template
class fmt::basic_format_arg
6、兼容性
类fmt::basic_string_view
template
class fmt::basic_string_view
c++17以前, std::basic_string_view 的实现,其提供了一个子集的API
fmt::basic_string_view 可以用来格式化字符串,即使std::string_view可以有效避免当使用与客户端代码不同的-std选项编译库时问题:
公有函数:
6.1)、basic_string_view重载
constexpr basic_string_view(const Char s, size_t count)
根据C字符串和大小,构造一个字符串引用对象。
6.2)、basic_string_view重载
basic_string_view(const Char s)
从C字符串构造一个字符串引用对象,该字符串使用std :: char_traits :: length计算大小。
6.3)、basic_string_view重载
template
basic_string_view(const std::basic_string &s)
从std :: basic_string对象构造一个字符串引用。
6.4)、data原型:
constexpr const Char data() const
返回指向字符串数据的指针。
6.5)、size
constexpr size_t size() const
返回字符串的大小
该类提供了对宽字符的支持
using fmt::string_view = typedef basic_string_view[span style="color: rgba(0, 0, 255, 1)">char
using fmt::wstring_view = typedef basic_string_view
7、本地化
默认情况下,所有格式化与语言环境无关。使用'n'格式,从本地语言环境中插入适当的数字分隔符,例如:
#include
#include
std::locale::global(std::locale("en_US.UTF-8"));
auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"
C、format API#
fmt/format.h定义了完整格式化的API,提供了编译时格式字符串检查,宽字符串,输出迭代器和用户定义的类型支持。
内置格式和字符串类型以及格式定义专长中具有constexpr解析函数的用户定义类型均支持编译时检查。
1、FMT_STRING(s)
从字符串常量s构造一个编译时格式字符串。例如:
// A compile-time error because 'd' is an invalid specifier for strings.
std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
2、格式化用户定义的类型
要创建用户定义的类型格式表,请专门设置formatter 结构模板并实现解析和格式化方法:
#include
struct point { double x, y; };
template
struct fmt::formatter
{
// Presentation format: 'f' - fixed, 'e' - exponential.
char presentation = 'f';
// Parses format specifications of the form 【'f' | 'e'】.
constexpr auto parse(format_parse_context& ctx) {
// auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) // c++11
// 【ctx.begin(), ctx.end()) is a character range that contains a part of
// the format string starting from the format specifications to be parsed,
// e.g. in
//
// fmt::format("{:f} - point of interest", point{1, 2});
//
// the range will contain "f} - point of interest". The formatter should
// parse specifiers until '}' or the end of the range. In this example
// the formatter should parse the 'f' specifier and return an iterator
// pointing to '}'.
// Parse the presentation format and store it in the formatter:
auto it = ctx.begin(), end = ctx.end();
if (it != end && (it == 'f' || it == 'e')) presentation = it++;
// Check if reached the end of the range:
if (it != end && it != '}')
throw format_error("invalid format");
// Return an iterator past the end of the parsed range:
return it;
}
// Formats //代码效果参考:http://www.jhylw.com.cn/183030045.html
the point p using the parsed format specification (presentation)// stored in this formatter.
template
auto format(const point& p, FormatContext& ctx) {
// auto format(const point &p, FormatContext &ctx) -> decltype(ctx.out()) // c++11
// ctx.out() is an output iterator to write to.
return format_to(
ctx.out(),
presentation == 'f' ? "({:.1f}, {:.1f})" : "({:.1e}, {:.1e})",
p.x, p.y);
}
};
然后,传递指针对象给任何函数:
point p = {1, 2};
std::string s = fmt::format("{:f}", p);
// s == "(1.0, 2.0)"
还可以通过继承或组合来重用现有的格式化器,例如:
enum class color {red, green, blue};
template struct fmt::formatter: formatter
{
// parse is inherited from formatter.
template
auto format(color c, FormatContext& ctx)
{
string_view name = "unknown";
switch (c)
{
case color::red: name = "red"; break;
case color::green: name = "green"; break;
case color::blue: name = "blue"; break;
}
return formatter::format(name, ctx);
}
};
由于解析是从formatter 继承的,因此它将识别所有字符串格式规范,例如:
fmt::format("{:>10}", color::blue)
这行代码将会返回一个字符串:" blue"。
可以为类的层次结构编写格式化器:
#include
#include
struct A
{
virtual ~A() {}
virtual std::string name() const { return "A"; }
};
struct B : A
{
virtual std::string name() const { return "B"; }
};
template
struct fmt::formatter
fmt::formatter
{
template