最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

TinyFormat 源碼閱讀(三)

2022-09-08 00:21 作者:Meriex  | 我要投稿

回顧一下昨天的部分我們讀到了 formatImpl 的實(shí)現(xiàn), printFormatStringLiteral 函數(shù)找到字符串格式化字符前的部分并寫入流,返回剩余的部分。

接著我們看一下 streamStateFromFormat 的實(shí)現(xiàn):

我們可以看到函數(shù)的主要功能就是解析諸如 %04d 這樣的格式化字符并為 ostream 設(shè)置輸出格式,這里遵循的是 C99 標(biāo)準(zhǔn)中的規(guī)范:

具體的就不多展開了,有興趣可以自己了解一下,這里我們專注語(yǔ)言上的一些風(fēng)格和技巧。

回到 formatImpl 函數(shù)中,一部分的流格式設(shè)置和 arg 填充在 streamStateFromFormat 中完成了,而另一部分則通過 arg.format 完成:

這里可以看到通過模板和宏配合聲明并定義了四個(gè) formatValue 函數(shù):

因此對(duì)于 char/signed char/unsigned char 這三種類型優(yōu)先調(diào)用非模板版本也就是直接向流中寫入數(shù)據(jù),而對(duì)于其他的版本則調(diào)用模板版本做進(jìn)一步的處理。

在模板版本的 formatValue 中對(duì)傳入的 value 分四種情況進(jìn)行處理:

  1. 能隱式轉(zhuǎn)化成 char 并且格式化字符也確實(shí)是 c 的,通過 formatValueAsType::invoke 調(diào)用 static_cast 轉(zhuǎn)成 char 類型并寫入流

  2. 能隱式轉(zhuǎn)為 const void* 且格式化字符為 p 的,同樣轉(zhuǎn)化后寫入流

  3. 需要截?cái)嗟?,只寫入截?cái)嗲安糠值搅髦?/p>

  4. 其他情況的直接通過 << vaule 寫入,依賴類型自身支持

以上過程又被 formatImpl 在一個(gè) while 循環(huán)中重復(fù),就這樣完成了字符串格式化的整個(gè)過程并由 oss.str() 返回。

到這里的話 TinyFormat 庫(kù)的基本邏輯我們都說完了,接下來說說關(guān)于變長(zhǎng)參數(shù)部分的拓展,之前在第一節(jié)分析 tinyformat_test.cpp 的時(shí)候我們分析了 TINYFORMAT_ARGTYPESTINYFORMAT_FOREACH_ARGNUM ?等宏的實(shí)現(xiàn),以及如何依靠這些宏完成對(duì)變長(zhǎng)參數(shù)的支持,那么在 c++11 加入了對(duì)變長(zhǎng)參數(shù)的支持后,我們又該怎樣實(shí)現(xiàn)這些函數(shù)呢。

FormatListN 的構(gòu)造函數(shù)為例, c++98 版本的實(shí)現(xiàn)如下 :

簡(jiǎn)單回顧一下,這里使用一個(gè)空的 init 函數(shù)作為中止函數(shù),接著借助宏實(shí)例化出最多支持 16 個(gè)參數(shù)的構(gòu)造函數(shù)和 init 函數(shù),嘗試初始化時(shí)由對(duì)應(yīng)參數(shù)數(shù)量版本的構(gòu)造函數(shù)從下標(biāo) i=0 開始調(diào)用 init 函數(shù),逐次遞增下標(biāo)并去除已賦值的參數(shù)直到所有參數(shù)全部初始化完成。

這是 c++11 支持變長(zhǎng)參數(shù)的版本:

可以看到這里通過 template<typename ... Args> 聲明 FormatListN 的構(gòu)造函數(shù)是一個(gè)模板函數(shù),并且接受變長(zhǎng)模板參數(shù)。同時(shí)很精巧的令 m_formatterStore 是一個(gè) FormatArg 類型的數(shù)組,且其構(gòu)造函數(shù)可以接收任意類型 T ,還通過 FormatListN 的模板參數(shù) template <size_t N> 來保證傳入的模板參數(shù)個(gè)數(shù)和數(shù)組長(zhǎng)度一直,因此可以直接通過 m_formatterStore { FormatArg(args)... } 把模板參數(shù)一次性復(fù)制給數(shù)組,非常有趣的一種寫法,否則的話一般來說即使是變長(zhǎng)模板參數(shù)也需要通過遞歸的方式完成賦值( c++17 可以用括號(hào)展開, c++11 用初始化列表魔法)。

特別注意由于這里使用內(nèi)置數(shù)組,因此我們要通過偏特化的方式對(duì)長(zhǎng)度為零的 FormatListN 進(jìn)行處理:

最后再來看一下通過 makeFormatList 構(gòu)造參數(shù)的部分,同樣是 c++11 實(shí)現(xiàn)的版本:

可以看到這里借助了 sizeof...(Args) 拿到了 FormatListN 所需要的模板參數(shù) N ,并傳入所有參數(shù)用以構(gòu)建和初始化參數(shù)列表。

好了,那么對(duì) TinyFormat 庫(kù)的整個(gè)閱讀到這基本上就結(jié)束了,從這個(gè)簡(jiǎn)小但功能強(qiáng)大的庫(kù)中我們收獲了一些常見的宏語(yǔ)法、對(duì)變長(zhǎng)模板參數(shù)的使用以及一個(gè)非常精妙的利用變長(zhǎng)模板參數(shù)向數(shù)組復(fù)制的小技巧。

下次再會(huì)!


TinyFormat 源碼閱讀(三)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
扎兰屯市| 临武县| 礼泉县| 扶余县| 靖江市| 宁强县| 竹溪县| 临澧县| 安吉县| 五家渠市| 霍城县| 南皮县| 连山| 北海市| 荆州市| 康马县| 芷江| 永福县| 屯门区| 肇庆市| 星子县| 津市市| 大邑县| 海兴县| 上栗县| 通许县| 连山| 稷山县| 山东省| 富宁县| 方正县| 新化县| 云梦县| 景宁| 台南县| 修水县| 眉山市| 陈巴尔虎旗| 曲周县| 瑞安市| 城口县|