技术经验分享: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

相关文章
|
3月前
|
监控 安全 测试技术
深入理解后端技术中的API设计原则
在当今数字化时代,后端技术已成为构建高效、可扩展和安全应用程序的关键因素。本文将探讨后端开发中的API设计原则,包括RESTful架构、版本控制以及安全性等方面,旨在帮助开发者提升API设计的质量和用户体验。通过对这些原则的深入理解,可以更好地满足业务需求并提高系统的可靠性。
68 0
|
2月前
|
安全 物联网 API
API技术之身份认证
【10月更文挑战第17天】身份认证是API安全的核心,确保API可信可控。
API技术之身份认证
|
2月前
|
JSON 前端开发 测试技术
API接口 |产品经理一定要懂的10%技术知识
作为产品经理,掌握约10%的技术知识对处理API相关工作至关重要。这包括理解API的基本概念及其作为数据交换的桥梁作用;熟悉JSON和XML两种主要数据格式及其特点;了解常见HTTP请求方法(GET、POST、PUT、DELETE)及响应状态码;关注API安全性,如认证授权和数据加密;掌握API版本管理和错误处理技巧;重视性能优化,以提升用户体验;参与API联调测试,确保稳定可靠;并与前后端团队紧密协作,选择合适的第三方API服务,推动产品高效开发。
|
2月前
|
XML API 网络架构
API协议 的十种技术特点及适用场景
本文介绍了十种常见的API协议技术,包括REST、GraphQL、gRPC、SOAP、WebSocket、AMF和XML-RPC等,每种技术都有其特点和适用场景,如REST适用于轻量级Web服务开发,gRPC适合高性能分布式系统,而WebSocket则适用于需要低延迟交互的应用。
|
2月前
|
SQL Java API
深入探索Java的持久化技术——JPA(Java Persistence API)
【10月更文挑战第10天】深入探索Java的持久化技术——JPA(Java Persistence API)
61 0
|
2月前
|
Java API 数据库
深入探索Java的持久化技术——JPA(Java Persistence API)
【10月更文挑战第10天】深入探索Java的持久化技术——JPA(Java Persistence API)
47 0
|
3月前
|
缓存 测试技术 API
电商平台 API 接入技术要点深度剖析
本文介绍了高效使用电商平台API的关键步骤。首先,深入理解API文档,明确功能权限与参数格式要求;其次,选择合适的接入方式,如HTTP/HTTPS协议和RESTful API;接着,实施身份验证与授权机制,确保数据安全传输;此外,还需关注性能优化、安全防护、监控与日志记录,以提升系统稳定性和响应速度;最后,进行充分测试与调试,并关注API版本更新,确保长期兼容性。
|
2月前
|
安全 NoSQL 测试技术
商品详情API接口的技术实现
本文介绍了电商平台上商品详情API接口的设计与实现过程,涵盖需求分析、接口定义、数据模型设计及技术选型等方面。通过合理的后端框架、数据库设计和安全措施,确保接口高效、稳定和安全。最后,通过详尽的测试与部署步骤,实现优质购物体验。旨在为技术人员提供实用参考。
|
3月前
|
设计模式 测试技术 API
Micronaut魔法书:揭秘构建超光速RESTful API的绝密技术!
【9月更文挑战第10天】在现代Web开发中,构建RESTful API至关重要。Micronaut作为一款轻量级框架,能够快速创建高效API。本文探讨使用Micronaut构建RESTful API的最佳设计模式与实践,涵盖注解(如`@Controller`、`@Get`)、代码组织、REST原则、数据验证及测试等方面,帮助开发者构建结构清晰、可维护性强的API服务。示例代码展示了如何使用Micronaut实现用户管理API,强调了良好设计模式的重要性。
60 3
|
3月前
|
自然语言处理 搜索推荐 数据挖掘
电商 API 接口:电商领域的强大技术引擎
在数字化浪潮中,电商API接口作为连接系统的桥梁,已成为电商市场的核心技术引擎。它通过实时库存信息、多样化支付等功能提升用户体验,支持自动化订单处理,促进数据流通与分析,并允许定制化开发,集成移动应用,从而增强系统灵活性和业务竞争力。