C++中的std--format 如何实现编译期格式检查.docx

C++中的std--format 如何实现编译期格式检查.docx

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多

C++中的std::format?如何实现编译期格式检查

C++20的std::format是一个很神奇、很实用的工具,最神奇的地方在于它能在编译期检查字符串的格式是否正确,而且不需要什么特殊的使用方法,只需要像使用普通函数那样传参即可。

#includeformat

inta=1;

std::strings1=std::format(a:{},a);//OK

std::strings2=std::format(a:{},b:{},a);//编译错误

C++20的std::format来自一个著名的开源库{fmt}。在C++20之前,fmt需要为每个字符串字面量创建不同的类型才能实现编译期格式检查。fmt提供了一个FMT_STRING宏以简化使用的流程。

#includefmt/format.h

inta=1;

std::strings1=fmt::format(FMT_STRING(a:{}),a);//OK

std::strings2=fmt::format(FMT_STRING(a:{},b:{}),a);//编译错误

C++20有了consteval后就不用这么别扭了。consteval函数与以前的constexpr函数不同,constexpr函数只有在必须编译期求值的语境下才会在编译期执行函数,而consteval函数在任何情况下都强制编译期求值。std::format就是利用consteval函数在编译期执行代码,来检查字符串参数的格式。

然而std::format自身不能是consteval函数,只好曲线救国,引入一个辅助类型std::format_string,让字符串实参隐式转换为std::format_string。只要这个转换函数是consteval函数,并且把格式检查的逻辑写在这个转换函数里面,照样能实现编译期的格式检查。

这里我们实现了一个极简版的format,可以检查字符串中{}的数量是否与参数的个数相同。format_string的构造函数就是我们需要的隐式转换函数,它是一个consteval函数。若字符串中{}的数量不对,则代码会执行到throw这一行。C++的throw语句不能在编译期求值,因此会引发编译错误,从而实现了在编译期检查出字符串的格式错误。

namespacemy{

templateclass...Args

classformat_string{

private:

std::string_viewstr;

public:

templateclassT

requiresstd::convertible_toconstT,std::string_view

constevalformat_string(constTs)

:str(s)

std::size_tactual_num=0;

for(std::size_ti=0;i+1str.length();i++){

if(str[i]=={str[i+1]==}){

actual_num++;

constexprstd::size_texpected_num=sizeof...(Args);

if(actual_num!=expected_num){

throwstd::format_error(incorrectformatstring);

std::string_viewget()const{returnstr;}

templateclass...Args

std::stringformat(format_stringstd::type_identity_tArgs...fmt,Args...args){

//省略具体的格式化逻辑

}

有一个细节,此处format函数的参数写的是format_stringstd::type_identity_tArgs...,直接写format_stringArgs...是无法隐式转换的,因为模板实参推导(templateargumentdeduction)不会考虑隐式转换,C++20提供了一个工具std::type_identity可以解决这个问题。std::type_identity其实就是一个关于类型的恒等函数,但是这么倒腾一下就能在模板实参推导中建立非推导

文档评论(0)

135****8957 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档