技术经验分享:fmt的API介绍(版本:7.0.1)

简介: 技术经验分享:fmt的API介绍(版本:7.0.1)

!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!!


作者: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

相关文章
|
2天前
|
JSON 数据可视化 API
技术心得:如何用Python和API收集与分析网络数据?
技术心得:如何用Python和API收集与分析网络数据?
10 2
|
3天前
|
域名解析 JavaScript 网络协议
技术心得记录:如何使用google地图的api(整理)
技术心得记录:如何使用google地图的api(整理)
|
9天前
|
Java Linux API
微信API:探究Android平台下Hook技术的比较与应用场景分析
微信API:探究Android平台下Hook技术的比较与应用场景分析
|
2月前
|
Java Unix 关系型数据库
时间API在更新,传奇已经谢幕,但技术永远不死
时间API在更新,传奇已经谢幕,但技术永远不死
|
2月前
|
存储 Java 应用服务中间件
4.基础技术&API网关&JWT
4.基础技术&API网关&JWT
23 1
|
2月前
|
存储 安全 机器人
【LLM】智能学生顾问构建技术学习(Lyrz SDK + OpenAI API )
【5月更文挑战第13天】智能学生顾问构建技术学习(Lyrz SDK + OpenAI API )
69 1
|
26天前
|
Java API Maven
第三方支付API支付宝支付申请流程 支付宝新老版本
第三方支付API支付宝支付申请流程 支付宝新老版本
35 0
|
2月前
|
存储 安全 API
网络安全与信息安全:防御前线的关键技术深入理解RESTful API设计原则与实践
【5月更文挑战第30天】在数字化时代,网络安全和信息安全已成为维系信息社会运行的核心支柱。本文深入探讨了网络安全漏洞的概念、加密技术的进展以及提升安全意识的重要性。通过对这些领域的分析,旨在为读者提供一个关于如何保护个人和组织资产免遭网络威胁的综合性视角。 【5月更文挑战第30天】 在现代Web服务开发领域,表述性状态传递(REST)已成为构建后端API的一种流行且成熟的架构风格。本文将探讨RESTful API的核心设计原则,并通过实例分析如何将这些原则应用于实际开发中。我们将重点讨论资源的概念化、HTTP方法的正确使用、状态码的准确传达以及API的可扩展性和版本控制问题。通过本文,读者将
|
2月前
|
缓存 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
【4月更文挑战第30天】Flutter允许开发者通过`CustomPaint`和`CustomPainter`进行自定义绘制,以实现丰富视觉效果。`CustomPaint` widget将`CustomPainter`应用到画布,而`CustomPainter`需实现`paint`和`shouldRepaint`方法。`paint`用于绘制图形,如示例中创建的`MyCirclePainter`绘制蓝色圆圈。Canvas API提供绘制形状、路径、文本和图片等功能。注意性能优化,避免不必要的重绘和利用缓存提升效率。自定义绘制让Flutter UI更具灵活性和个性化,但也需要图形学知识和性能意识。
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
|
1天前
|
JSON 安全 API
如何高效编写API接口:以Python与Flask为例
构建RESTful API的简明教程:使用Python的Flask框架,从环境准备(安装Python,设置虚拟环境,安装Flask)到编写首个API(包括获取用户列表和单个用户信息的路由)。运行API服务器并测试在`http://127.0.0.1:5000/users`。进阶话题包括安全、数据库集成、API文档生成和性能优化。【6月更文挑战第27天】
17 7