FMT--现代格式库

2020-05-25 06:25:35

{fmt}是C++的开放源码格式库,可以安全快速地替代printf和iostream。

高性能:比printf和ostream的通用标准库实现更快。请参阅C++中的速度测试和快速整数到字符串转换。

源代码(最低配置仅由core.h、format.h和format-inl.h三个头文件组成)和编译代码都很小。请参见编译时间和代码膨胀。

安全性:该库是完全类型安全的,可以在编译时报告格式字符串中的错误,自动内存管理可防止缓冲区溢出错误。

fmt::print(";Hello,{}!";,";world";);//类似Python的格式字符串语法fmt::printf(";Hello,%s!";,";world";);//printf格式字符串语法。

std::string s=fmt::format(";I';D宁愿是{1}而不是{0}。(";,";Right";,";);//s=";I';I";I&/s=#34;I';我宁愿快乐也不愿正确。

$c++-iinclude-std=c++14 test.cc.test.cc:4:17:注意:在函数模板专门化实例化';fmt::v5::format<;S,int>;';请求的herestd::string s=format(fmt_string(";{2}";),42);^include/fmt/core.h:778:19:注意:无。^INCLUDE/fmt/Format.h:2226:16:注意:在调用';&;checker.context_->;on_error(&;";argument索引时超出范围";[0])';CONTEXT_.ON_ERROR(";参数索引超出范围";);^。

fmt::memory_buffer buf;format_to(buf,";{}";,42);//替换itoa(42,buffer,10)format_to(buf,";{:x}";,42);//替换itoa(42,buffer,16)//使用to_string(Buf)或buf.data()访问字符串

#include";fmt/format.h";struct date{int年,月,日;};模板<;>;struct fmt::Formatter<;date>;{stexpr auto parse(format_parse_context&;ctx){返回ctx。Begin();}Template<;TypeName FormatContext>;Auto Format(Const Date&;d,FormatContext&;CTX){Return Format_To(CTX.。out(),";{}-{}-{}";,D.年,D.月,D.日);}};std::string s=fmt::format(";日期为{}";日期{2012,12,9});//s==";日期为2012-12-9";

//打印格式化的错误消息。void vreport_error(const char*format,fmt::format_args args){fmt::print(";error:";);fmt::vprint(format,args);}模板<;typeName.。参数&>void REPORT_ERROR(常量字符*格式,常量参数(&A;).。args){vreport_error(format,fmt::make_format_args(args.));}report_error(";找不到文件:{}";,路径);

请注意,与完全参数化的版本相比,vreport_error不在参数类型上参数化,这可以缩短编译时间并减少代码大小。

以上结果是通过使用clang++-O3-DSPEED_TEST-DHAVE_FORMAT在macOS10.14.6上构建tinyformat_test.cpp并取三次运行中的最佳结果生成的。在测试中,格式字符串";%0.10f:%04d:%+g:%s:%p:%c:%%\n";或等效字符串填充了2,000,000次,并将输出发送到/dev/null;。有关详细信息,请参阅源代码。

{fmt}在浮点格式化(dtoa-Benchmark)上比std::ostrg stream和spintf快10倍,与双重转换一样快:

脚本bloat-test.pyfrom格式基准测试重要项目的编译时间和代码膨胀。它生成100个翻译单元,并在每个单元中使用printf()或它的交替使用5次来模拟中型项目。生成的可执行文件大小和编译时间(Apple LLVM版本8.1.0(clang-802.0.42)、MacOS Sierra,三选一)如下表所示。

如您所见,就产生的二进制代码大小而言,{fmt}的开销比iostream少60%,与printf非常接近。Boost Format和Folly Format的管理费用最大。

printf+string与printf相同,但使用额外的<;string>;include来测量后者的开销。

libc、lib(Std)c++和libfmt都链接为共享库,仅用于比较格式化函数开销。Boost格式是仅限标题的库,因此它不提供任何链接选项。

有关如何构建库和运行单元测试的说明,请参阅构建库。

基准位于单独的存储库中,即格式基准,因此要运行基准,您首先需要克隆此存储库并使用CMake生成Makefile:

Scylla:与Cassandra兼容的NoSQL数据存储,可以在一台服务器上每秒处理100万个事务。

如果您知道有其他使用此库的项目,请通过电子邮件或提交问题的方式让我知道。

完成这项任务的方法有很多,从标准的printf函数系列和iostream到Boost Format和FastFormatlibrary,不一而足。创建一个新库的原因是,我发现的每个现有解决方案要么都存在严重问题,要么没有提供我需要的所有功能。

printf的好处是,作为C标准库的一部分,它相当快,而且很容易获得。主要缺点是它不支持用户定义的类型。printf也存在安全问题,尽管使用__ATTRIBUTE__((format(printf,.))可以稍微缓解这些问题。在GCC中,有一个POSIX扩展,它将i18nto printf所需的位置参数添加到printf中,但它不是C99的一部分,在某些平台上可能不可用。

“快速格式”(FastFormat)一书的作者马修·威尔逊(Matthew Wilson)称这是雪佛龙地狱。IOStreamsdon故意不支持位置参数。

好的方面是,iostream支持用户定义的类型并且是安全的,尽管错误处理很笨拙。

这是一个功能非常强大的库,既支持类似printf的格式化字符串,也支持位置参数。它的主要缺点是性能。根据各种基准测试,它比这里考虑的其他方法要慢得多。BoostFormat还存在构建时间过长和严重的代码膨胀问题(请参阅基准测试)。

这是一个有趣的库,它快速、安全并且有位置参数。然而,它有很大的限制,引用它的作者的话:

它也相当大,并且有一个很重的依赖,STLSoft,这对于在一些项目中使用它可能是有限制的。

这并不是一个真正的格式库,但为了完整起见,我决定将其包含在这里。作为iostream,它存在逐字混合文本和参数的问题。该库相当快,但是在整数格式上比在Karma自己的基准上的fmt::format_int要慢,请参阅C++中的快速整数到字符串转换。

模板类型名称(<;TypeName).。参数自动捕获(常量参数(&A;).。args){return std::make_tuple(args.);}AUTO PRINT_MESSAGE=[](const auto&;.。args){fmt::print(args.);};//捕获和存储参数:auto args=catch(";{}{}";,42,";foo";);//执行格式化:std::Apply(print_message,args);

文档中的格式字符串语法部分基于适用于当前库的Python String module ocumentation中的格式字符串语法部分。出于这个原因,本文档是根据Python Software Foundation许可证分发的,可在doc/python-License se.tx.tx.中找到。它仅适用于您分发FMT文档的情况。

{fmt}库由Victor Zverovich(Vitaut)和Jonathan Müller(Foonathan)维护,其中有许多其他人的贡献。请参阅贡献者和发布者了解其中一些名称。如果您的贡献没有被正确列出或提及,请让我们知道,我们会纠正您的贡献。(注:{fmt}库是由Victor Zverovich(Vitaut)和Jonathan Müller(Foonathan)维护的。请参阅贡献者和发布者)。

本自述文件的基准测试部分和性能测试来自Chris Foster编写的优秀tinyformat库。Boost格式库是公认的,因为它对tinyformat产生了一些影响。实现中使用的一些想法借鉴了Loki SafeFormat和Clang中的Diagnostic API。Format字符串语法和文档基于Python的str.format。感谢Doug Turnbull对类型安全API的设计提出的宝贵意见和贡献,以及Gregory Chaajkowski实现二进制格式化的贡献。感谢Ruslan Baratov对整数格式化算法的全面比较和有关性能的有用评论,感谢Boris Kaul为C++计数数字基准所做的贡献。感谢CarterLi对代码做出的各种改进。