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

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

TinyFormat 源碼閱讀(一)

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

慚愧很久沒有更新B站了,博客也很少寫,隨便開個(gè)坑吧,一個(gè)閱讀源碼的系列,主要找一些質(zhì)量不錯(cuò)的小型項(xiàng)目/庫(kù),也同時(shí)學(xué)習(xí)一下。


首先看一下項(xiàng)目簡(jiǎn)介:

tinyformat.h is a type safe printf replacement library in a single C++ header file. If you've ever wanted?printf("%s", s) to just work regardless of the type of?s, tinyformat might be for you.

tinyformat.h 是一個(gè)類型安全的 header only(只包含單個(gè)頭文件) 的 printf 替換庫(kù)。如果你曾經(jīng)想過 printf("%s", s) 可以在無(wú)論 s 的類型如何的情況下都能正常工作,那么 tinyformat 可能就是你要的。

我們可以首先看一下 CMakeLists.txt 來決定我們閱讀源碼的順序:

tinyformat 是一個(gè) header only 的庫(kù)也就是只包含頭文件,使用時(shí)不需要鏈接而只需要 include 的庫(kù),因此我們?cè)?CMakeLists.txt 中看不到一個(gè)庫(kù)相關(guān)的 target ,但是可以先通過項(xiàng)目中的測(cè)試用例也就是 tinyformat_test 來對(duì)整個(gè)庫(kù)建立一個(gè)直觀的印象。

因此我們首先閱讀 tinyformat_test.cpp 文件,沒有使用測(cè)試框架,而是自己定義了一些宏作為輔助:

從名字能看出這個(gè)宏的目的是期待在測(cè)試中出現(xiàn)錯(cuò)誤,整個(gè)執(zhí)行塊被包含在 try/catch 中,首先執(zhí)行傳入的 expression 語(yǔ)句,如果執(zhí)行過程中存在異常拋出,那么接下來的代碼不會(huì)被執(zhí)行到,直接被捕獲并忽略,如果沒有拋出異常那么會(huì)觸發(fā) ++nfailed 表示測(cè)試結(jié)果與行為不符,并在 log 中打印失敗的測(cè)試用例。不過這里只對(duì) std::runtime_error 類型的異常做了處理算是一個(gè)小瑕疵。


這個(gè)也比較簡(jiǎn)單,如果 a 不等于 b 就會(huì)觸發(fā) ++nfailed ,不過這里有一些小細(xì)節(jié)要說一下,第一個(gè)是之所以這里把參數(shù)都用括號(hào)括起來是一個(gè)好的習(xí)慣,有助于我們約束宏的行為防止一些意料之外的錯(cuò)誤,第二個(gè)是即使這樣錯(cuò)誤還是不可避免,比如這里如果我們以下面的兩種方式使用 CHECK_EQUAL 宏:

我們就會(huì)發(fā)現(xiàn) aCHECK_EQUAL 中自增的次數(shù)其實(shí)是不一致的,這很容易導(dǎo)致我們無(wú)法預(yù)測(cè)宏的行為,這也是為什么越來越多的人不推薦使用宏的原因:

甚至可以看到 3 != 3 這樣的神奇現(xiàn)象,如果在一個(gè)復(fù)雜項(xiàng)目中出現(xiàn)這種日志會(huì)讓我們非常頭疼


從名字中的 Wrap 以及注釋能看出這是使用 tfm::format 來包裝和創(chuàng)建一些東西,結(jié)合用例:

可以看出用法還是比較簡(jiǎn)單的,本身庫(kù)的作用就是替換 printf ,因此傳入 std::fmt 的后幾個(gè)參數(shù) "asdf" 等都被拼到 someformat %s:%d:%d 中,最后通過 m_oss.str() 一并返回到 CHECK_EQUAL 中和 "10: someformat asdf:2:4" 進(jìn)行比較,那結(jié)果應(yīng)該是正確的。

接著看一下實(shí)現(xiàn), 首先能看到 TestWrap::error 這個(gè)模板函數(shù)不是直接定義的,而是由 MAKE_ERROR_FUNC 通過 TINYFORMAT_FOREACH_ARGNUM 生成,前者很簡(jiǎn)單就是一個(gè)包含實(shí)現(xiàn)的宏,我們主要看一下后者,在項(xiàng)目頭文件中找到的定義如下:

這個(gè)寫法現(xiàn)在看來很丑很難理解,實(shí)際上考慮到這是一個(gè)基于 c++11 且多年沒有更新的項(xiàng)目是正常的,因?yàn)楫?dāng)時(shí)的 c++ 沒有對(duì)變長(zhǎng)模板參數(shù)的支持,因此這種寫法甚至在舊版本的 boost 實(shí)現(xiàn)中也有用到?;氐?TINYFORMAT_FOREACH_ARGNUM 的定義,實(shí)際就是實(shí)例化出傳入的函數(shù)參數(shù) m 也就是 MAKE_ERROR_FUNC 的 16 個(gè)版本,因此我們需要再次回到 MAKE_ERROR_FUNC 的實(shí)現(xiàn)中。

可以看到對(duì) n 的多次使用,首先是 TINYFORMAT_ARGTYPES(n) ,剛剛說了這種是用來代替變長(zhǎng)模板參數(shù),于是我們直接找一下定義應(yīng)該也是類似的:

沒錯(cuò)就是這么丑,通過 ## 連接 TINYFORMAT_ARGTYPES_ 和模板參數(shù)長(zhǎng)度生成宏的名字并返回對(duì)應(yīng)長(zhǎng)度的模板參數(shù),以 template<TINYFORMAT_ARGTYPES(2)> 為例返回的就是 template<class T1, class T2> ,其他兩個(gè)宏 TINYFORMAT_VARARGSTINYFORMAT_PASSARGS 實(shí)現(xiàn)也基本相同這里不再贅述。


那實(shí)現(xiàn)中宏的部分和上面的類似,也是生成了不同參數(shù)長(zhǎng)度版本的構(gòu)造函數(shù)。這里 TestExceptionDef 是一個(gè)自定義的異常類型,繼承自 std::runtime_error ,構(gòu)造時(shí)通過 tfm::format 傳入解釋異常原因的提示信息。

后續(xù)的話就是一些測(cè)試用例了,那么對(duì) tinyformat_test.cpp 測(cè)試代碼部分的閱讀我們就到此為止,下一篇我們將會(huì)正式從 tfm::format 函數(shù)開始窺探整個(gè)庫(kù)的運(yùn)行機(jī)制,感謝大家的閱讀,再會(huì)!

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

分享到微博請(qǐng)遵守國(guó)家法律
廉江市| 海淀区| 稷山县| 密云县| 玉屏| 璧山县| 阳泉市| 阿瓦提县| 洛南县| 泾川县| 芦山县| 孝昌县| 双城市| 左贡县| 汤阴县| 阳原县| 城口县| 张掖市| 华蓥市| 金门县| 阿勒泰市| 江门市| 通州区| 梨树县| 新和县| 青州市| 白河县| 阿瓦提县| 湄潭县| 临江市| 常宁市| 中宁县| 铜陵市| 南溪县| 凯里市| 昌平区| 贺兰县| 德钦县| 旅游| 泰来县| 泗水县|