亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

C++模板學(xué)習(xí)筆記:從編譯期代碼生成到C++20 Concepts

C++模板學(xué)習(xí)筆記:從編譯期代碼生成到C++20 Concepts C模板一直是我學(xué)習(xí)之路上繞不過去的一座山。寫這篇學(xué)習(xí)筆記之前我已經(jīng)在項(xiàng)目里被模板編譯錯(cuò)誤折磨過好多次——明明照著文檔寫了編譯器就是看不懂我的代碼。后來我換了個(gè)思路去理解它模板根本不是“帶類型的函數(shù)”而是一套讓類型作為參數(shù)參與編譯的代碼生成機(jī)制。想通這一點(diǎn)之后之前那些報(bào)錯(cuò)突然就變得有跡可循了。這篇文章可以看成我重新整理過的C模板學(xué)習(xí)筆記從函數(shù)模板和類模板的基礎(chǔ)語法開始一路講到特化、變參模板、模板元編程再到C20的Concept。適合兩類人讀一是剛開始接觸模板、想系統(tǒng)建立概念的初學(xué)者二是寫過一點(diǎn)模板代碼但經(jīng)常被編譯錯(cuò)誤卡住、想提升排查能力的人。我會(huì)把每一部分都配合真實(shí)可運(yùn)行的代碼片段順帶分享一些我在實(shí)際開發(fā)中被坑過的地方。1. 模板到底解決了什么問題從重復(fù)代碼到類型參數(shù)化1.1 一段讓我決定認(rèn)真學(xué)模板的重復(fù)代碼兩年前我在某個(gè)內(nèi)部工具項(xiàng)目里寫過一段“三胞胎”代碼。需求很簡單求兩個(gè)值里的較大者但調(diào)用方有時(shí)傳int有時(shí)傳double有時(shí)傳std::string。我當(dāng)時(shí)的做法是完全復(fù)制粘貼改一改參數(shù)類型和函數(shù)名像這樣int max_int(int a, int b) { return a b ? a : b; } double max_double(double a, double b) { return a b ? a : b; } std::string max_string(const std::string a, const std::string b) { return a b ? a : b; }三個(gè)函數(shù)邏輯一模一樣只是類型不同。更麻煩的是后來需求變了比較規(guī)則從“大于”改成“絕對(duì)值更大”我就要同步修改三處代碼漏改一處線上行為就會(huì)出現(xiàn)詭異的不一致。那段時(shí)間我深刻體會(huì)到一個(gè)道理重復(fù)代碼的維護(hù)成本是乘積增長的而不只是求和。真正讓我下定決心啃模板的就是這一堆不斷擴(kuò)散的“三胞胎”。1.2 模板的“編譯期鴨子類型”實(shí)例化才是核心用模板改寫上面的問題代碼量立刻縮成一份template typename T T my_max(const T a, const T b) { return a b ? a : b; }關(guān)鍵在于理解上面的my_max并不是一個(gè)真正的函數(shù)它只是一份“函數(shù)藍(lán)圖”。編譯器看到my_max(1, 2)時(shí)會(huì)用int替換掉模板參數(shù)T生成一份針對(duì)int的真實(shí)函數(shù)看到my_max(1.5, 2.5)時(shí)再生成一份針對(duì)double的。這個(gè)過程叫模板實(shí)例化發(fā)生在編譯期運(yùn)行期完全不感知模板的存在。我習(xí)慣用模具來類比模板是模具本身實(shí)例化出來的函數(shù)才是被沖壓出的零件。同一個(gè)模具改變?cè)牧项愋途湍茏龀霾煌馁|(zhì)但形狀相同的零件。這個(gè)理解幫我解決了很多疑惑——比如為什么模板類可以接受那些只支持部分操作的類型因?yàn)槌蓡T函數(shù)是按需實(shí)例化的你沒用到某個(gè)成員函數(shù)編譯器就不會(huì)去檢查它內(nèi)部的運(yùn)算合不合法。1.3 模板代碼與普通代碼的三點(diǎn)不同在實(shí)際工程里模板代碼給人的“脾氣”和普通函數(shù)很不一樣我總結(jié)了三條最重要的差異第一運(yùn)行期開銷為零。模板實(shí)例化在編譯期完成生成的是普通函數(shù)沒有虛函數(shù)那樣的間接跳轉(zhuǎn)沒有額外的運(yùn)行時(shí)類型信息。作為對(duì)比如果用基類指針加虛函數(shù)實(shí)現(xiàn)類似效果運(yùn)行期每一次調(diào)用都要查虛函數(shù)表。第二錯(cuò)誤往往出現(xiàn)在使用處而不是定義處。模板定義本身經(jīng)常是“法外之地”比如上面my_max要求類型支持operator。你把這個(gè)模板定義放在頭文件里編譯器不會(huì)立刻報(bào)錯(cuò)只有在某個(gè)使用處傳入一個(gè)不支持operator的類型時(shí)編譯器才會(huì)把長長的實(shí)例化調(diào)用鏈甩到你臉上。第三定義必須可見。普通函數(shù)可以聲明在頭文件、定義在源文件鏈接器最后把它們拼起來模板不行因?yàn)閷?shí)例化需要看到完整定義。很多新手第一次寫模板習(xí)慣性地把實(shí)現(xiàn)放在.cpp里結(jié)果一鏈接變成一堆“undefined reference”這是模板學(xué)習(xí)的第一個(gè)經(jīng)典大坑。這三條差異構(gòu)成了理解后面所有內(nèi)容的基礎(chǔ)。我見過太多人糾結(jié)模板語法本身卻忽略了模板的“編譯期代碼生成”本質(zhì)導(dǎo)致遇到報(bào)錯(cuò)時(shí)無從下手。2. 函數(shù)模板與類模板入門第一步的關(guān)鍵細(xì)節(jié)2.1 函數(shù)模板的參數(shù)推導(dǎo)與顯式指定函數(shù)模板最讓人舒爽的一點(diǎn)是大部分時(shí)候不需要你手動(dòng)指定類型編譯器會(huì)自動(dòng)推導(dǎo)模板參數(shù)auto v1 my_max(1, 2); // T推導(dǎo)為int auto v2 my_max(1.5, 2.5); // T推導(dǎo)為double auto v3 my_max(a, z); // T推導(dǎo)為char但推導(dǎo)并不是萬能的。我踩過的第一個(gè)坑是調(diào)用my_max(1, 2.5)時(shí)編譯器直接報(bào)錯(cuò)“template argument deduction failed”。原因是模板參數(shù)T同時(shí)出現(xiàn)在const T a和const T b兩個(gè)位置編譯器遇到int和double兩種實(shí)參時(shí)無法確定T到底該選哪個(gè)。這時(shí)候有兩個(gè)選擇顯式指定模板參數(shù)讓int隱式轉(zhuǎn)換成double或者修改模板讓兩個(gè)參數(shù)接受不同類型。auto v my_maxdouble(1, 2.5); // 顯式指定T為double顯式指定模板參數(shù)的一個(gè)常見場(chǎng)景是函數(shù)參數(shù)和返回值類型有關(guān)聯(lián)但又不完全能從參數(shù)推導(dǎo)出來比如想要返回值類型和某個(gè)參數(shù)類型不同時(shí)。另一個(gè)容易忽略的規(guī)則形如const T的參數(shù)推導(dǎo)時(shí)T剝掉引用和頂層const。比如傳一個(gè)const int進(jìn)去T推導(dǎo)為int而不是const int。這個(gè)細(xì)節(jié)在涉及類型萃取和完美轉(zhuǎn)發(fā)時(shí)會(huì)變得非常重要建議一開始就有意識(shí)地去注意。2.2 類模板的靜態(tài)成員與友元函數(shù)三個(gè)容易混淆的點(diǎn)類模板的語法本身并不復(fù)雜無非是把類變成“模具”template typename T class Box { public: static int count; T value; void print() const; }; template typename T int BoxT::count 0;但有三個(gè)點(diǎn)我直到實(shí)際寫代碼時(shí)才真正理解第一個(gè)是靜態(tài)成員屬于每個(gè)實(shí)例。Boxint和Boxdouble各自擁有一份獨(dú)立的count因?yàn)樗鼈儽举|(zhì)上是兩個(gè)不同的類。你可以在Boxint里累加計(jì)數(shù)Boxdouble::count依然是0兩者互不影響。第二個(gè)是成員函數(shù)按需實(shí)例化。如果某個(gè)類型可以構(gòu)造出Box但print()內(nèi)部調(diào)用了這個(gè)類型不支持的接口只要整個(gè)程序里沒有調(diào)用過Box該類型::print()編譯就能通過。這種“懶加載”特性在泛型約束不足的時(shí)候很危險(xiǎn)——你可能以為所有類型都支持某個(gè)操作結(jié)果撐到運(yùn)行時(shí)才炸。第三個(gè)是友元聲明用法特殊。在類模板里聲明友元函數(shù)模板要么用friend void func(T);聲明依賴模板參數(shù)的友元要么用template typename U friend void func(U);聲明一個(gè)獨(dú)立的友元模板。寫錯(cuò)的情況下你會(huì)得到一堆“鏈接錯(cuò)誤”或者“重復(fù)聲明”的奇怪報(bào)錯(cuò)。2.3 為什么模板的聲明和定義不能分開放這個(gè)問題被問過無數(shù)次也是我最早踩的坑之一。普通函數(shù)可以這樣寫// foo.h int add(int a, int b); // foo.cpp int add(int a, int b) { return a b; }編譯時(shí)使用add的源文件只要看到聲明就生成調(diào)用代碼至于定義在哪鏈接器負(fù)責(zé)去找。模板不一樣編譯器在需要實(shí)例化template typename T T my_max(...)的時(shí)候必須看到模板的完整定義才能往里填入T并生成代碼。如果頭文件里只有聲明調(diào)用處只知道“有這么個(gè)模板”卻不知道函數(shù)體是什么編譯器就只能放棄把問題留給鏈接器于是出現(xiàn)一堆完全看不懂的undefined reference。解決方案主要有兩種。最常用的是把模板實(shí)現(xiàn)也寫在頭文件里這也是標(biāo)準(zhǔn)庫一直以來的做法另一種是在源文件里顯式實(shí)例化比如// template_impl.cpp template int my_maxint(const int, const int); template double my_maxdouble(const double, const double);這相當(dāng)于提前把指定類型的實(shí)例生成好鏈接器就能找到定義。但顯式實(shí)例化的缺點(diǎn)也很明顯每個(gè)需要用到的類型都得手寫一遍一旦類型多起來維護(hù)成本比重復(fù)代碼還可怕。所以絕大部分項(xiàng)目都會(huì)選擇第一種“頭文件內(nèi)定義”的方式。3. 模板特化與偏特化編譯器在分支路口如何做選擇3.1 全特化的寫法與適用場(chǎng)景模板實(shí)例化時(shí)編譯器默認(rèn)是用一個(gè)統(tǒng)一“模具”生成代碼。但某些類型可能有更好的實(shí)現(xiàn)方式這時(shí)就可以為特定類型開小灶這就是全特化。比如前面那個(gè)my_max遇到const char*這種C風(fēng)格字符串如果用默認(rèn)的operator去比較比的是指針地址而不是字符串內(nèi)容結(jié)果完全不符合直覺。這時(shí)候可以寫一個(gè)全特化版本template const char* my_maxconst char*(const char* const a, const char* const b) { return std::strcmp(a, b) 0 ? a : b; }全特化的關(guān)鍵字是template 后面跟一個(gè)完全確定類型的函數(shù)或類定義。編譯器在為const char*做實(shí)例化時(shí)會(huì)優(yōu)先找到這個(gè)特化版本而不是通用模板。我當(dāng)時(shí)的理解是通用模板是默認(rèn)工廠流程全特化是給特定訂單單獨(dú)開了一條生產(chǎn)線。不過這里必須提醒一句函數(shù)模板的全特化其實(shí)很容易被忽略尤其在存在函數(shù)重載的時(shí)候。編譯器選擇順序是先看非模板函數(shù)再看模板特化最后才看模板實(shí)例化。如果項(xiàng)目中同時(shí)存在一個(gè)同名同參的非模板函數(shù)和一個(gè)全特化版本非模板函數(shù)往往被優(yōu)先選中這個(gè)行為常常讓人困惑。所以我在實(shí)踐中更傾向于用函數(shù)重載而不是函數(shù)模板全特化但類模板沒有重載這回事只能特化。3.2 類模板偏特化指針、引用與const的幾種典型偏特化類模板只有全特化和偏特化沒有“重載”。偏特化是指保留部分模板參數(shù)只對(duì)某一種模式做專門處理。最常見的應(yīng)用場(chǎng)景是針對(duì)指針類型、引用類型、const類型做差異處理。template typename T class Wrapper { public: T data; }; // 針對(duì)指針類型的偏特化 template typename T class WrapperT* { public: T* ptr; }; // 針對(duì)const類型的偏特化 template typename T class Wrapperconst T { public: T value; // 注意這里T本身剝掉了const };偏特化的本質(zhì)是“模式匹配”。WrapperT*匹配任何指針類型Wrapperconst T匹配任何const類型。編譯器會(huì)按匹配程度選一個(gè)最合適版本比如Wrapperconst int*既可以被WrapperT*匹配Tconst int也可以被Wrapperconst T匹配Tint*但最終選擇時(shí)部分特化與參數(shù)模式的貼合程度會(huì)被比較通常T*更貼合因?yàn)橥饷嬉粚邮侵羔樓覂?nèi)部是const int。這里有個(gè)細(xì)節(jié)我原來常弄混偏特化只能用于類模板不能用于函數(shù)模板。函數(shù)模板想要類似效果應(yīng)該用重載。所以如果有人試圖給函數(shù)模板寫template typename T void funcT*(T*)這樣的偏特化語法編譯器會(huì)直接拒絕。3.3 特化與重載的優(yōu)先級(jí)一個(gè)讓我調(diào)試到崩潰的例子有一次我在項(xiàng)目里給一個(gè)工具庫寫了這樣的代碼template typename T void handle(const T value) { std::cout generic std::endl; } template void handleint(const int value) { std::cout int specialization std::endl; } void handle(const int value) { std::cout non-template overload std::endl; }調(diào)用handle(42)時(shí)我滿心以為輸出的是int specialization結(jié)果控制臺(tái)打印出來的是non-template overload。查了好半天才發(fā)現(xiàn)編譯器在選擇重載時(shí)非模板版本優(yōu)先于模板特化版本。這條規(guī)則我后來在標(biāo)準(zhǔn)條款里確認(rèn)過如果非模板函數(shù)和模板特化都能匹配非模板函數(shù)優(yōu)先。這件事給我的教訓(xùn)是不要試圖用函數(shù)模板特化去“覆蓋”重載決議它的行為既不直觀又容易讓維護(hù)者誤會(huì)。函數(shù)模板想針對(duì)特定類型做區(qū)分正確姿勢(shì)是寫一個(gè)更特化的函數(shù)重載或者用后面會(huì)講到的if constexpr/概念約束。類模板特化才是干凈利落的解決方案。4. 變參模板與折疊表達(dá)式簡化重復(fù)代碼的實(shí)用工具4.1 參數(shù)包展開的三種方式變參模板variadic templates是我學(xué)會(huì)之后覺得“真香”的特性。它允許模板接受任意數(shù)量、任意類型的參數(shù)。C11引入時(shí)主要是為了配合完美轉(zhuǎn)發(fā)實(shí)現(xiàn)工廠函數(shù)后來C17折疊表達(dá)式讓這個(gè)語法又好寫了非常多。先看最經(jīng)典的遞歸展開方式。要打印任意個(gè)參數(shù)可以這樣void print_all() { // 遞歸終止函數(shù)空參數(shù)包時(shí)結(jié)束 } template typename T, typename... Args void print_all(const T first, const Args... rest) { std::cout first ; print_all(rest...); // 每次剝掉一個(gè)參數(shù) }typename... Args聲明一個(gè)參數(shù)包Args... rest在函數(shù)參數(shù)列表中表示一組參數(shù)。遞歸展開每次取出第一個(gè)參數(shù)剩下的繼續(xù)遞歸直到參數(shù)包為空時(shí)調(diào)用無參重載。這是最直觀的展開方式邏輯清晰但每層遞歸都要生成一個(gè)新模板實(shí)例編譯代價(jià)略高。第二種方式是用初始化列表配合逗號(hào)表達(dá)式一次性展開template typename... Args void print_all_init(const Args... args) { (void)std::initializer_listint{ (std::cout args , 0)... }; }這里的(std::cout args , 0)是個(gè)逗號(hào)表達(dá)式先執(zhí)行打印再生成一個(gè)int類型的0整個(gè)表達(dá)式結(jié)果就是0于是可以放進(jìn)std::initializer_listint。...把參數(shù)包展開成一組用逗號(hào)分隔的表達(dá)式。這個(gè)寫法不需要遞歸模板實(shí)例化層級(jí)少編譯效率更好缺點(diǎn)是讀起來比較勸退。第三種方式是在C17里最簡單直接的——折疊表達(dá)式下面單獨(dú)說。4.2 折疊表達(dá)式C17之后的簡潔寫法折疊表達(dá)式讓變參模板的可讀性提升了一大截。它的語法看一眼就明白一半template typename... Args void print_all_fold(const Args... args) { (std::cout ... args) std::endl; }這個(gè)表達(dá)式(std::cout ... args)是左折疊等價(jià)于把a(bǔ)rgs從左到右依次拼到std::cout上。對(duì)于打印這種沒有累積結(jié)果的場(chǎng)景更常用的是逗號(hào)折疊template typename... Args void print_all_fold2(const Args... args) { ((std::cout args ), ...); std::cout std::endl; }逗號(hào)折疊會(huì)把每個(gè)參數(shù)依次打印出來中間的逗號(hào)不是打印內(nèi)容而是折疊操作符。我當(dāng)時(shí)第一次看到(...)這個(gè)寫法有點(diǎn)懵但只要記住一點(diǎn)折疊表達(dá)式是對(duì)參數(shù)包做一次編譯期的二元?dú)w約一元右折(args op ...)從最后一個(gè)參數(shù)開始一元左折(... op args)從第一個(gè)參數(shù)開始。折疊表達(dá)式特別適合做求和、拼接、邏輯與這類累積操作。比如template typename... Args auto sum_all(Args... args) { return (args ... 0); // 二元折疊初始值0避免空包報(bào)錯(cuò) }注意空參數(shù)包時(shí)沒有初始值的折疊表達(dá)式是非法的所以求和時(shí)最好加上一個(gè)初始值。4.3 變參模板在工廠函數(shù)與完美轉(zhuǎn)發(fā)中的應(yīng)用變參模板最常見的一個(gè)實(shí)際場(chǎng)景是寫工廠函數(shù)。標(biāo)準(zhǔn)庫里的std::make_shared、std::make_unique本質(zhì)就是變參模板加完美轉(zhuǎn)發(fā)。一個(gè)簡化版本可以這樣寫template typename T, typename... Args std::shared_ptrT my_make_shared(Args... args) { return std::shared_ptrT(new T(std::forwardArgs(args)...)); }這里的關(guān)鍵是Args... args和std::forwardArgs(args)...。Args不是普通的右值引用而是轉(zhuǎn)發(fā)引用也叫萬能引用它可以根據(jù)實(shí)參自動(dòng)推導(dǎo)成左值引用或右值引用。std::forward的作用是保留參數(shù)原有的值類別如果調(diào)用方傳進(jìn)來的是一個(gè)左值就按左值轉(zhuǎn)發(fā)如果是右值就按右值轉(zhuǎn)發(fā)。這樣一來構(gòu)造函數(shù)里不會(huì)因?yàn)閰?shù)中途丟失“移動(dòng)語義”或“拷貝語義”而引發(fā)不必要的拷貝。我第一次接觸這個(gè)寫法時(shí)總是想不通為什么要這么繞。后來我明白了在模板函數(shù)內(nèi)部具名的參數(shù)都是左值哪怕實(shí)參原本是右值。如果不加std::forward原本可以移動(dòng)構(gòu)造的對(duì)象被迫拷貝構(gòu)造性能白白損失。這個(gè)細(xì)節(jié)在寫高性能容器、事件分發(fā)系統(tǒng)時(shí)非常關(guān)鍵。5. 模板元編程與類型萃取把運(yùn)行期的判斷搬到編譯期5.1std::is_same和std::enable_if的搭配模板真正強(qiáng)大的地方不只在于生成代碼還在于可以在編譯期“根據(jù)類型做判斷”。C11標(biāo)準(zhǔn)庫提供了大量類型萃取工具比如std::is_sameT, U專門用來判斷兩個(gè)類型是否一致。但如果你直接這么寫多半會(huì)掉坑里template typename T void process(const T value) { if (std::is_sameT, int::value) { // 假設(shè)這里調(diào)用了value.someIntMethod() } else { // 假設(shè)這里調(diào)用了value.someStringMethod() } }問題在于模板實(shí)例化時(shí)if的兩個(gè)分支都會(huì)被編譯無論T是int還是std::string兩個(gè)分支里那些“不存在的方法”都會(huì)導(dǎo)致編譯失敗。運(yùn)行期判斷無法阻止編譯期錯(cuò)誤。正確做法是讓不滿足條件的分支從編譯過程里直接消失。std::enable_if就是為此設(shè)計(jì)的template typename T typename std::enable_ifstd::is_sameT, int::value, void::type process(const T value) { std::cout 處理int std::endl; } template typename T typename std::enable_if!std::is_sameT, int::value, void::type process(const T value) { std::cout 處理其他類型 std::endl; }std::enable_if條件, 類型::type只在條件為真時(shí)才存在條件為假時(shí)整個(gè)函數(shù)聲明就是非法的編譯器直接丟棄這個(gè)重載。這相當(dāng)于在編譯期做了一次“替換失敗不是錯(cuò)誤”SFINAE的篩選。不過說實(shí)話這種寫法讀起來很拗口。C17之后有了if constexpr相同場(chǎng)景簡單得多template typename T void process(const T value) { if constexpr (std::is_sameT, int::value) { // 只在T是int時(shí)編譯 } else { // 只在T不是int時(shí)編譯 } }if constexpr的真正意思是“在編譯期選擇一個(gè)分支另一個(gè)分支不實(shí)例化”。這比enable_if直觀太多所以我的經(jīng)驗(yàn)是新項(xiàng)目盡量用if constexprenable_if更多用于需要參與重載決議的場(chǎng)合。5.2 一個(gè)編譯期階乘模板理解遞歸實(shí)例化的邊界模板元編程最經(jīng)典的教學(xué)示例是在編譯期計(jì)算階乘。用模板遞歸來實(shí)現(xiàn)template int N struct Factorial { static const int value N * FactorialN - 1::value; }; // 偏特化/特化提供遞歸終止條件 template struct Factorial0 { static const int value 1; }; // 用法 static_assert(Factorial5::value 120, 5! should be 120);這段代碼展示了一個(gè)元編程的核心模式用模板參數(shù)驅(qū)動(dòng)遞歸用特化提供終止條件。Factorial5實(shí)例化時(shí)需要Factorial4Factorial4又需要Factorial3……直到Factorial0這個(gè)特化版本提供了出口。我在學(xué)習(xí)時(shí)問過自己既然C11就有constexpr函數(shù)了為什么還要研究模板遞歸因?yàn)閮烧邆?cè)重點(diǎn)不同。constexpr函數(shù)是可以被編譯期計(jì)算的普通函數(shù)寫法更自然適用范圍更廣但模板遞歸可以在“編譯期產(chǎn)生類型”比如根據(jù)整數(shù)常量生成不同的類型結(jié)構(gòu)這是constexpr函數(shù)做不到的?,F(xiàn)代C實(shí)踐中復(fù)雜元編程確實(shí)越來越少用“階乘”這種把戲但理解遞歸實(shí)例化對(duì)弄明白模板是怎么一層層展開出錯(cuò)誤信息非常有幫助。5.3 元編程的局限編譯時(shí)間、可讀性與維護(hù)成本我見過有些開發(fā)者學(xué)會(huì)模板元編程后恨不得把所有邏輯塞進(jìn)編譯期結(jié)果項(xiàng)目編譯時(shí)間從十幾秒暴漲到幾分鐘。元編程是有代價(jià)的每一層模板實(shí)例化編譯器都要做一次“類型替換 模式匹配 代碼生成”復(fù)雜元程序甚至?xí)?shí)例化成千上萬個(gè)模板錯(cuò)誤信息動(dòng)輒幾百行。更麻煩的是可維護(hù)性。元編程代碼常?!胺慈祟悺睕]有正常的循環(huán)和變量只有遞歸和常量調(diào)試器里幾乎看不到運(yùn)行時(shí)的中間值加了static_assert可能還好一旦缺少診斷信息后人維護(hù)時(shí)只能靠猜。我的經(jīng)驗(yàn)法則很簡單能用constexpr函數(shù)算出來的就別用模板元編程能用運(yùn)行期算的也別硬搬進(jìn)編譯期。模板元編程最適合處理的是“類型的選擇與轉(zhuǎn)換”比如判斷某類型是否滿足某接口、在不同類型之間做編譯期分發(fā)。至于業(yè)務(wù)計(jì)算交給constexpr函數(shù)和普通函數(shù)就好別為了炫技把整個(gè)項(xiàng)目拖入編譯地獄。6. C20 Concepts讓模板報(bào)錯(cuò)從“天書”變成人話6.1 定義一個(gè)自己的概念直到C20之前模板的約束只能靠enable_if這種“負(fù)向篩選”。問題是當(dāng)約束不滿足時(shí)編譯器給出的錯(cuò)誤信息往往是一大串“模板參數(shù)推導(dǎo)失敗候選模板被忽略”完全沒有告訴你“為什么失敗”。Concepts概念就是為了解決這個(gè)問題。概念定義看起來像對(duì)類型的一組“體檢要求”。舉個(gè)例子我想定義一個(gè)“可相加的”概念#include concepts template typename T concept Addable requires(T a, T b) { { a b } - std::convertible_toT; };這里requires后面跟的花括號(hào)是個(gè)requires表達(dá)式里面可以寫三類要求簡單要求表達(dá)式合法、類型要求typename后面跟的類型存在、復(fù)合要求{表達(dá)式} - 約束既要求表達(dá)式合法又要求結(jié)果滿足某個(gè)約束。上面的概念表示T類型要滿足任意兩個(gè)T對(duì)象相加的結(jié)果必須能轉(zhuǎn)換成T。如果某個(gè)類型不支持operator或者加出來的結(jié)果不是T概念檢查就失敗。6.2 把概念用進(jìn)函數(shù)模板的三種寫法定義好概念后約束函數(shù)模板有多種等效寫法我三種都在項(xiàng)目里見過// 寫法一requires子句 template typename T requires AddableT T add(T a, T b) { return a b; } // 寫法二約束模板參數(shù) template Addable T T add(T a, T b) { return a b; } // 寫法三約束auto參數(shù) Addable auto add(Addable auto a, Addable auto b) { return a b; }這三種寫法表達(dá)的是同一個(gè)意思選哪種更多是風(fēng)格問題。我個(gè)人的偏好是第二種template Addable T它把約束直接寫進(jìn)模板參數(shù)列表讀起來最自然。第一種適合約束條件比較復(fù)雜、需要多行requires表達(dá)式的情況。第三種雖然簡潔但適合用在約束很輕的場(chǎng)景如果概念本身很復(fù)雜會(huì)讓函數(shù)聲明顯得擁擠。概念帶來的最大好處是錯(cuò)誤信息質(zhì)量顯著提升。當(dāng)你用一個(gè)不支持的類型去調(diào)用add時(shí)編譯器會(huì)直接告訴你“約束未滿足因?yàn)镾omeType不滿足Addable”。雖然還是有一定閱讀門檻但相比之前滿屏的模板參數(shù)替換記錄已經(jīng)像人話了。6.3 概念對(duì)重載決議的影響與注意點(diǎn)概念不只是語法糖它還參與重載決議。簡單說更受約束的函數(shù)模板在重載時(shí)會(huì)勝出。比如template typename T requires std::integralT void test(T) { std::cout 整型版本 std::endl; } template typename T requires std::signed_integralT void test(T) { std::cout 有符號(hào)整型版本 std::endl; }如果調(diào)用test(3)兩個(gè)模板都能匹配但std::signed_integral比std::integral更嚴(yán)格多了“有符號(hào)”的限制編譯器認(rèn)為它的約束更“受約束”所以第二個(gè)版本勝出。這個(gè)機(jī)制叫約束偏序編譯器會(huì)自動(dòng)比較兩個(gè)約束的邏輯包含關(guān)系。這里要特別注意一點(diǎn)約束偏序的判斷依賴于約束表達(dá)式本身的結(jié)構(gòu)不一定總能推導(dǎo)出“更嚴(yán)格”。如果兩個(gè)概念之間沒有明顯的蘊(yùn)含關(guān)系調(diào)用時(shí)就會(huì)報(bào)重載歧義。我在寫具有多個(gè)約束版本的重載時(shí)會(huì)刻意給概念起名并保持概念的邏輯層級(jí)清晰比如Integral和SignedIntegral這種直接體現(xiàn)包含關(guān)系的命名重載決議和行為都更容易預(yù)測(cè)。7. 我踩過的模板編譯錯(cuò)誤與排查思路7.1 從“no matching function”到真正的調(diào)用棧模板編譯報(bào)錯(cuò)最常見的開頭就是error: no matching function for call to ...緊跟著一屏幕候選模板。剛開始我每次都從第一行開始讀結(jié)果一頭扎進(jìn)幾百行的“模板實(shí)例化調(diào)用鏈”里出不來。后來我總結(jié)出一個(gè)更高效的排查順序先看調(diào)用點(diǎn)的實(shí)參類型是否和函數(shù)模板參數(shù)匹配。比如傳了一個(gè)std::string但函數(shù)參數(shù)是const T這通常沒問題但如果實(shí)參是int*模板參數(shù)又是T推導(dǎo)結(jié)果就是int*后續(xù)函數(shù)體里若把它當(dāng)成整數(shù)用就會(huì)報(bào)錯(cuò)。所以先確認(rèn)推導(dǎo)出來的T是什么再往函數(shù)體里看。其次檢查返回值類型相關(guān)表達(dá)式。很多“no matching function”并不是調(diào)用參數(shù)不匹配而是返回值類型所在的enable_if條件不滿足整個(gè)候選模板被SFINAE規(guī)則丟棄。最后才去看輸出列表末尾那幾行“實(shí)例化自”位置那里通常指向你業(yè)務(wù)源碼中真正出錯(cuò)的那一行。編譯器的調(diào)用鏈?zhǔn)菑哪0宥x開始展開的最底部的層次往往才是你的業(yè)務(wù)調(diào)用點(diǎn)從下往上讀會(huì)更高效。7.2 模板定義必須可見鏈接期錯(cuò)誤的定位還有一類錯(cuò)誤不在編譯期爆發(fā)而是藏在鏈接期。典型報(bào)錯(cuò)是undefined reference to void my_maxint(const int, const int)這個(gè)報(bào)錯(cuò)信息里甚至有模板參數(shù)int但很多人第一眼看不出它和模板有什么關(guān)系。原因就是前面說過的模板的定義放在了.cpp里調(diào)用方頭文件里只有聲明實(shí)例化被迫中斷最后鏈接器發(fā)現(xiàn)找不到對(duì)應(yīng)符號(hào)。遇到這種報(bào)錯(cuò)排查路徑是先去檢查該模板定義所在文件是否被包含在調(diào)用方的編譯單元里再確認(rèn)是否有人在.cpp里做了顯式實(shí)例化但拼錯(cuò)了類型。另一個(gè)容易忽略的情況是類模板的靜態(tài)成員定義忘了寫這也會(huì)在鏈接期出現(xiàn)類似“undefined reference toBoxint::count”的報(bào)錯(cuò)解決方式是回到類外補(bǔ)上模板靜態(tài)成員的定義。7.3 用靜態(tài)斷言和“類型打印”工具輔助診斷排查模板類型推導(dǎo)問題時(shí)我特別依賴一個(gè)“手工類型打印”的技巧。核心思路是寫一個(gè)故意不定義的模板類讓編譯器在報(bào)錯(cuò)時(shí)把類型“帶”出來template typename... struct TypePrinter; // 故意不定義 template typename T void debug_type(T) { // 觸發(fā)編譯錯(cuò)誤報(bào)錯(cuò)信息中會(huì)顯示T的類型 static_assert(sizeof(TypePrinterT) 0, 查看T的類型); }只要某個(gè)地方調(diào)用了debug_type(expr)編譯器就會(huì)在static_assert那里報(bào)錯(cuò)錯(cuò)誤信息里會(huì)顯示TypePrinterint或者TypePrinterconst char ()[6]這類類型全名。這種手段在排查引用、const、數(shù)組退化的推導(dǎo)問題時(shí)比任何調(diào)試器都好用。另一個(gè)常用工具是static_assert搭配類型萃取static_assert(std::is_samedecltype(x), int::value, 這里推導(dǎo)出來的類型不是int);一旦條件不滿足編譯器會(huì)把你寫的提示信息打印出來。我現(xiàn)在的習(xí)慣是在寫復(fù)雜的模板函數(shù)時(shí)先在關(guān)鍵推導(dǎo)點(diǎn)放幾個(gè)臨時(shí)的static_assert確定類型無誤后再刪掉。這比依賴IDE的類型懸停提示更可靠因?yàn)榫幾g器的推導(dǎo)結(jié)果才算是最終事實(shí)。最后再分享一點(diǎn)我的個(gè)人體會(huì)。模板學(xué)習(xí)切忌只看語法一定要親手編譯看報(bào)錯(cuò)修報(bào)錯(cuò)。我建議初學(xué)者不要急著上模板元編程先把函數(shù)模板、類模板、特化、變參模板這四塊跑熟再試Concept。模板報(bào)錯(cuò)確實(shí)難看但看得多了你會(huì)發(fā)現(xiàn)它其實(shí)有規(guī)律可循編譯器會(huì)把整個(gè)實(shí)例化調(diào)用鏈展開你只要從最底層的一條開始看。后續(xù)我還會(huì)繼續(xù)整理模板相關(guān)的學(xué)習(xí)筆記比如模板參數(shù)推導(dǎo)的完整規(guī)則和約束偏序的細(xì)節(jié)那又是兩個(gè)大坑。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
国语精品av| 婷婷去俺也去六月色| 五月天久久久| 成人三一级一片aaa| 97在线观看| 久久精品日韩专区免费观看| 中文字幕 一区二区 亚洲无码| 影音先锋少妇| 性爱乱伦网址| 人人射人人操人人摸| 亚洲一区中文精品| 精品人妻少妇| 亚州色图片在线色| 亚洲男人的天堂在线看| 伊人久久国产免费观看视频| 精品人妻伦一二三区久久| 无码 黑人一区二区三区| 欧美天天| 久久久久久久9| 亚洲自拍欧美国产首页网曝| 麻豆天美久久91| 黄色大香焦1级‘′‘| 青娱乐999| 精人妻一区二区三区| 我中文字幕6区| 色色色综合| 天天躁日日躁XXXXYY| 超碰在线人人射| 99久草| 天天色欧美| 久操免费视频| 中国韩国明星一极片一区乱码毛片人妻熟女一区二区三区 | 精品久操| 日本天堂在线播放| 中出20p| 白嫩91在线亚洲| 欧洲小说色图视频另类| 日韩人妻精品| 日韩亚洲97| 国产噜噜噜噜噜久久久久久久久| 自拍二页| 97chaopenrihan| 精品人妻一二三四区视频| 啊啊啊啊啊好大好舒服想要| 亚洲大胆人体av| 久草婷婷| 日本熟妇色熟妇在线视频播放| 熟女高潮合集-永久久久-成人AV | 好爽视频在线观看| 97国产|免费| 日本道人妻久久久在线不卡色视频| 国模91| 熟妇高潮精品一区二区三区下载| julia ann久久| 欧美韩日精品资源| 校园春色AV天堂| 大香蕉狠狠爱| 内射夫妻三片| 亚洲欧美日韩精品久| 免费一级特黄特色大片在线观看看| www.伪伪| 免费夜夜爱黄色视频毛片| 日本超碰在线国产一区| 综合国产97| 亚洲色图美腿丝袜| 日本ZZ高免费A级视频| 欧美日韩人妻精品系列一区二区三区| 国产精品蜜臀久久久久无码AV| 中文字幕日韩人妻视频一区二区三区| 日本一本道A级黄色毛片试看60分钟| 女人高潮抽搐喷水视频网站| 第二页中文字幕| 伊人aaa| 91久久婷婷| 黄片免费视频2019| 亚洲夜夜欢无码一区二区 | 风韵犹存大大大大香蕉| 午夜福利无毒不卡| 91欧美偷拍| 男人成人黄色视频在线观看免费下载| 亚洲电影中字一区二区| 丁香六月啪| 日本加靬比网站发布页| 激情婷婷丁香网| 3PAV乱伦视频| 国产家庭乱伦网址| 红桃视频高潮| 激情五月天中文字幕色| 亚洲AV免费在线| 欧美曰韩国产精品| 国产路线专区| 久久一级无码精品毛片6| 9999伦理视频| 天天亚洲| 国产色呦呦| 人人澡人人爽人人精品| 欧亚 另类 久| av凤凰久久久| 久久精品中文字幕女同| 蜜臀AV秘一区翔田千里| 男人久久天堂| 好爽,再快点啊哈嗯嗯嗯嗯| 精品一区二区在线针对华人免费观看这里只有精品免费观看 | 极品极品色影院| 你想操日本小逼吗| 东北黄色电影| 婷婷超| 少妇3P性爱自拍| 亚洲色图 欧美热图 清纯唯美 另类自拍 | 亚洲AV小说| 台湾成人无码AV| 黑人中出21连凳花野真衣| av72网| 97视频在线观看网站| 99999国产| 久久久久九九九九| 日韩av电影网站| 国产精品com| 综合网97| 老熟女91视频| 亚州欧美另类| 亚州色图狠狠干| 91色插| 熟女精品va中文字幕| 盗摄 精品 另类 一区| 龙兴卡官方查询| 中文字幕乱在线伦视频中文字幕乱码在线| 99色婷婷中文字幕乱色| 亚洲婷婷综合网| 97中文超碰| 91丝袜在线观看| 精品精品精品| 日韩啊V| 久久手机好看网站| 在线无码视频| 亚洲欲| 亚洲日韩成人性爱视频| 亚洲九九视频| 欧美亚州手机在线| 最新无码国产| 亚洲青青草| 久久久久久国产精品免费网站| 亚洲极品| 婷婷色香| 亚洲欧洲国产综合av| 日韩欧美久久婷婷网站| 在线啊啊啊啊| 国产乱色国产精品免费视| 亚洲美女30b| 黄色AAAAA欧美| 日本不卡二区| 欧美色图片91| 亚洲日韩国产欧美综合v| 午夜传煤十二区精品| 99re这里只有精品中心播放| 天天色黄色影院天天操| 亚欧美色图| 天天综合网~69| 99这里只有精品国产| 亚洲影视第一页| 禁片 高清 在线观看视频网站| 亚洲人妻中文在线视频| 日韩丨制服丨中文|在线| 国模精品一区二区三区苹果色戒| 日本欧美韩国国产在线| 丝袜美腿91| 啊啊啊啊啊在线观看网址| 免费1级a做爰片观看| 久久久久久少妇| 五月色综合| av毛片aaaaa免费看| 亚洲AV永久无码精品成人调教| 日韩少妇丰满亚洲| 丁香7月婷婷| 九九九九九九精品| 99热97| 国产一区二区三区中文字幕| 免费1级a做爰片观看| 久热网| 亚洲射综合网| 欧美亚洲首页| 免费操逼91| www.AV有限公司一区| 亚洲综合成人网| 秋霞网无码| 欧美色图99| 一区中文字幕二区日韩| 5月婷婷6月六月丁香| 一级性爱视频免费在线| 78久久| 亚欧洲一区二区视频| 91无人区卡一卡二卡三乱码入口最新版:能让用户有更多选择的选择-经典说说-爱 | 97在线观看播放视频| 亚洲黄色AV电影| 偷拍片久久| 97超碰色屌| 国产一区96在线| 欧美很很操视频| 婷婷丁香九月| 欧 美 自 拍 偷 拍| 日本精品999| 中文字幕黄色一起草| 欧美亚洲高清不卡| 亚洲日韩乱码中文无码蜜桃臀网站| 久久久久精| 亚洲中文字幕三级在线| 中文字幕 国产区| 亚洲成人一区二区精品| 强奸国产在线| 欧美系列在线一区二区| 婷婷五月天激情网| 欧美日韩性爱视屏免费看了| 亚洲第一在线视频| 99热这里是精品| 免费中文在线| 国产日韩精品一区二区三区| 九九这里只有精品| 水澄无码AV| 一区二区三区在线资源| 欧美熟妇人体| AV色五月天| 亚洲欧洲无码一区夜| 色网在线| 97ai亚洲| 成人精品在线免费视频| 亚洲无码超碰免费| 天天色天天干天天射| 日本操色导航| 伊人色综合网电影| 精品四五区| 久久久久久久久久久久久9999| 91男女啊啊啊| 日韩中文字幕宗合在线| 久操免费观看| 亚洲最新Av| 日本精品无码三级网站| 欧洲天天在线| 大香蕉男人的天堂| 加勒比色99999| 亚洲一区二区av| 蜜臀久久99精品久久久久久无删减| 男女做爰猛烈动高潮A片免费应用 少妇厨房愉情理伦片bd在线观看 不卡中文字幕aⅴ在线 | 国产51色综合久久免费| 大香樵伊人网| 国产美女91视频| 一本久久精品中文字| 亚洲人妻久久久| 蜜臀一区二区三区亚洲最新章节在线观看 - 高清蜜臀一区二区三区亚洲全集播放 | 美女网站黄页| 欧美aa一级片| 婷婷久久久| 中文字幕天天天天天| yy少妇精品久久| 97伊人超碰| 国产成人亚洲精品无码最新在线| 插欧洲美女欧美精品| 久久久精品国产亚洲伊人| 亚洲色性情三级| 夜夜嗨免费视频| 久久精品人妻一区| 无码视频黄色网战| 少妇人妻无码| 成人怡红院| 26uuu性| 精品一区二区三区蜜桃臀赵总 | 十八禁黄色成人网站观看| 久久噜噜噜精品国产亚洲综合| 999综合网| 又大又长又粗又爽又黄| 国产13区| 九九九九久久久久| 欧美性爱五月天| 天操老女人| 成人国产视频在线观看| 亚洲色久| 色哟哟av| 嫩草影院在线观看精品| 老司机免费视频在线91| 亚洲电影中字一区二区| 91neishe| 69一区二区| 欧美黄片视频在线观看免费| 亚洲综合 欧美| 日韩在线一区二区| 嗯嗯啊啊视频一区二区三区| 中英熟女操女| 色穴精品| 综合色色婷婷| 国产欧美黑人丰满在线| 国产精品亚洲天堂网址| 大香蕉中文aV在线| 免费人成毛片乱码| 精品久久99| 久草免费在线视频| 日韩草久视频| 思思热国产高清| 日韩精品区二区三区不卡| 日本二区不卡| 欧洲天天在线| 免费精品国偷自产在线在线| 九九九九九九九九九九九免费国产| 久久二| 亚洲欧美精品一区天堂久久 | 日韩无限资源| 好吊色一区| 日韩欧洲操屄视频| 久日91在线| 天天操夜夜嗨| 久久精品国产97欧美精品亚洲| 日韩性爱小视频在线观看| 色色青青久久| www.99色| 91久久| SS久久| 人干人人人操人人摸| 欧美色图91p| 日韩人妻 中文字幕| 91超碰在线播放| 日韩中文字幕二区| 亚洲欧美不卡线| 久久久久久久久久久97| 乱伦图av| 酒色综合网| 久久精品72| 在免费jIzzjIzz在线视频| 日韩成人人妻网站| 日韩人体偷拍| 亚洲第一黄色av网站 | 大伊香蕉在线视频免费| sewuyueav| 欧美日韩黄色片一区二区三区四区人与兽做爱| 欧美一区二区日韩三区| 丝袜色综合| 岛国小电影| 丝袜性亚洲| 顶级丝袜熟女一区二区三区 | 精品999一区二区| 麻豆av一区二区三区| www.99中文字幕| 91n处女在线观看| 国产怡红院| AV网站高清无码在线观看| 九九热精品视频六| 综合性视频99| 久久夜嗨| 开心激情站| 国产传媒午夜理伦精品| 少妇色欲综合网2| 久久欧洲| 97天天爽| 五月丁香激情综合| 操逼大黄片| 蜜臀久久99精品久久久久久| 吊色| 四虎AV影视国产精品亚洲精品| 久久精品国产72国产精品福利| 熟女人妻一区二区三区| 一二三区视频在线观看| 丝袜av一区二区三区| 亚洲男人天堂Av| aⅴ日韩成人电影av在线免费看av大全 | 思思热一热婷婷热一热| 91骚妇| 丁香五月激情综合| 天美麻花大全视频| 最新中文字幕精品在线| 亚洲AV无码乱码| 欧美日韩亚洲天堂| 久久无码一区二区二三区性色| 亚洲丝袜二区在线| 舔人妻中文免费视频| 国产极品久久久| 麻豆蜜桃视频在线观看| 天天日夜夜| 青青操轻轻| 欧亚乱色熟女一区二区| 韩国一级婬片A片无码天美 | 亚洲av热热色| 啊啊啊好舒服好爽啊啊啊视频| 中文高清一区二区的| 五月天色色色| 色综合色色| 高清无码国产亚洲| 激情色色| 九九热精品在线| 99热欧美| 一本一道人妻久久一区二区三区 | 玖色av| 日韩AV噜噜噜一区二区三区四区| 精品一区二区2| 无码九九九九| 亚洲日韩AV视色| 久久9视频| 超碰在线国产| 色色婷| 色婷婷香蕉| 激情综合五| 亚洲激情四射| 天堂资源欧美| 久久久久久久国产| 无卡一区=区| 一区二区三区男人的天堂| 精品九九国产无码| 蜜桃久久久久久久| 国产精品探花在线| 四月丁香婷婷| 超碰色男人操熟女| 家庭乱伦网站国产| www.色五月| 伊人97超碰| AV高清一区| 美女91色黄18| 好吊色青靑草| 在线观看成人性爱免费小视频| 欧美大波激情xxxx| 久久性爱网站| 欧美一区91大爱| 东京热一区二区三区四区五区六区| 九九热超碰97亚洲最新香蕉| 中文字幕一区二区三区蜜桃视频| 91另类| 欧美中文字幕日韩在线| 日韩去日本高清在| 超碰激情808| 亚洲日本天堂| 亚洲无码视频免费在线观看网址!| 国产黄色影片在线观看| 亚洲天堂99| 中文字幕55555| 欧美色爱综合| 五十路六十路七十路熟婆| 丁香五月激情综合国产| 操美女人妻| 蜜臀网址在线| 少妇无码av专区线| 99re9这里只有精品| 拍拍拍拍大尺度黄色三级片拍拍拍拍拍照| 欧美岛国精品在线观看| 大香蕉五月天| 中文字幕一品色图| 老熟妇一区二区三区…| 厕所偷拍在线| 青青草福利视频| 性爱1区| 欧美精品三区| 久久亚州精品成人Av无| 泰国AV在线观看| 国产91美女视频| 波多野结衣先锋影音| 婷婷三区| 中文字幕精品探花视频| 试看60秒| 2018天天日天天日| 日韩三四五区| 亚州男人天堂| 久久97| 久久婷婷苹果| 综合欧美日本三级| 中文字幕精品亚洲熟女| 18禁精品网站在线看| 久操高青| 乱伦日本中文自拍| 欧色综合| 国产极品精品美女视频| 久久天天躁日日躁狠狠躁 | 日韩无码操逼片| AV一二区| 91精品亚洲内射孕妇| 男人的天堂2018东京热啪啪啪| 精品无人区麻豆乱码1区2区图片 | 人人妻人人爽| 95人妻爽爽人人做人人澡| 婷婷九月丁香| 99∨VTV| 久久久久白虎| caorenqi shipin| 91九色丨风韵犹存| 日韩专区数据列表-第3230页-精品国产一区二区三区香蕉 久久99熟女人妻中文字 | 国产又爽又黄| 人人妻人人爽一区二区三区| 熟女丰满人妻一区| 97精品一区二区视频| 欧美美女在线高潮999| 国产成人拍国产亚洲精品| 激情网色| 天天色天天干天天射| dy888午夜老子影视达达兔| 天天干天天爽| 国产资源中文字幕在线| 黑丝日韩av丝袜av| 色青青久久影视| 欧中美三级一区二区三区| 加勒比大香蕉视频在线| 国产一级舔足在线观看| 国产乱码精品久久久久久| 大香蕉久| 色97干| 97人人爱人人做人人乐| 日韩亚洲Av人人夜夜澡人人爽| 日韩欧美久久婷婷网站| 午夜福利久久久噜久噜久久综合 | 综合网色| 永久免费av无码网站国产app| 精品久久九| 伊人久久艹| 欧美在线永久天堂| 久久风骚城市| 精品.99999| 久久久久久精品免费看A级| 91女日逼| 99re在线精品78| 国产超碰国产97| 日本欧美一区二区三区免费| 91老熟妇| 噜噜瑟| 天天日天天舔东京热| 久久婷婷亚洲| 乱伦1色页| 成人性生活高清视频在线播放| 欧美亚洲一区二区久久久婷精品大包诱| 屁屁影院一区二区三区国产| 亚洲 欧美 日韩 国产一区二区| 风月影院男女十八禁| 欧美专区在线| 日韩午夜啪啪视频| 思思热免费在线视频| 蜜臀久久99精品久久久久久婷婷| 六月婷婷一区二区三区| 内射中出日韩在线观看视频| 中文字幕成人| 国产精品久久久久中文字幕| 亚洲影院无码在线| 欧美日韩操逼嗦吊| 一级毛片电影免费看| 97超碰伊人| 亚州日韩97| 欧美亚综合色图| 婷婷综合视频| 五月天色图| 亚洲欧美国产其他二区| 亚洲日韩美国人妻| 99国产在线 精品 视频| 青春草莓视频在线观看网址| 欧美色另类| 蜜臀中文无码午夜| 丰满熟女人妻一区二区三五十一路| 日本东京热大香蕉a片| 久久久久久久久久久97| 殴美牲| 久久久久13| 亚州国产精品乱| 国内精品伊人久久久久影院会| 欧美色视频在线| 狠狠操官网| 无码高清少妇久久| 亚洲精品国产无码高清| 第四色奇米影视777| www.亚洲成人一区| 日本东京热久久久电影| 青青青国产手线观看视频2| 探花视频免费观看国产专区| 性天堂| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师黑人潮喷一 | 欧美狠狠弄| 日本一级特级毛片视频| 肉动漫无遮挡h在线观看| 日韩97P| 激情小说亚洲色图| 一区二区乱码福利| 午夜超碰| 97超碰精品成| 久久色AV线| 欧美色图片欧美色图| 美女让帅哥通她小鸡鸡| 日韩欧美久久婷婷网站| 97在线免费看视频| 天天综合网在线观看| 97免费在线视频| 亚洲欧美日韩制服另类| 国产隔壁老王影院在线| 国产欧美日韩精品中文| 99色天堂| 殴美日韩m| 中文字幕人乱码中文字的预防方法| www. 男人天堂成人在线| 91老熟女91老女人| 午夜传煤十二区精品| 好色综合| 99re公开精品免费视频 | 欧美大香蕉在线观看| 男人天堂久久日韩| 天天日骚逼熟女| 天美传媒婬乱在| 欧美夜夜草视频| 欧美aaaaaaa| 97综合在线| 91中文精品日韩欧美在线| 男人天堂久久精品不卡| 九九亚洲| 黑丝自慰喷水网站| 亚洲有薄码区日本系列中文字幕| 久久只有精品一区二区三区| 国产精品69久久久久久久| 60秒不遮不挡| 岛国视频一二三区| 九九亚洲| 玖玖爱综合网| 熟妇乱伦一区二区| 国产激情av女片自拍| 夜色五月天| 亚洲日韩乱码中文无码蜜桃臀网站| 精品国产乱码久久久影院| 色吧5亚洲| 丁香五月性| 在线情色电影 91大| 欧美翘臀视频网站一区二区三区| 1级黄色夫妻对换性交免费看| 欧美性爱五月天| 97在线观视频免费观看| 中文久久| 色五月综合| 亚洲怡春院| 免费αV在线视频| 九九碰九九爱97超碰| 亚洲精品 欧美精品| 国产在线观看一区二区三区| 国产亚洲在线观看| 精品视频久久区| 婷婷在线视频在线观看| 曰韩精品九九无码| AV中文字幕三四五| 国产麻豆福利av在线播放| 精品一区二区三区最新| 久久久久99999| 91粉嫩萝控精品福利网站_精品影音先锋国 | 色www精品视频在线观看| 超碰社区97| 天天干干天天干干| av情色影音| 亚欧美色| 熟女精品一区二区三区| 久久婷婷苹果| 欧美成人午夜免费福利785| 最新中文字幕av| 翔田千里AV无码秘 三区| 99热思思| 99久在线精品99re8蜜桃| 操逼网免费无码视频| 伊蕉97蜜桃97狠狠综合干| 97综合网| 中文字幕91综合| 加勒比综合88| 狠狠色色| 亚洲 日本 不卡| 人妻熟女av国产网站| 亚洲精品一卡二卡三卡福利视频网站 | 91影库| 九九夜精品九九在线| 女人精品内射国产99| 精品久一区免费| 国产亚洲色停停久久99精品91| 大香蕉伊人久久| 九九九偷拍| 色色热| 亚洲牲交| 久久中出在线| 欧美成人一级免费电影| 99视频自拍区| 久久女人一区二区三区| 午夜成人爽爽爽爽A片李冰冰| 男女91| 啪啪啪精品视频| 九九九九亚洲| 毛片17S| 免费看黄视频亚洲网站| 天天操福利视频综合网站| 天天日天天色| 日本人妻中文字幕精品| 久久精品女同亚洲女同13| 婷婷五月成人| 久久久久久久九九九九九九| 久久精品人妻一区二区三区| 小泽玛利亚一二三| 91人妻最真实刺激绿帽| 偷拍亚洲视频一区二区三区四区| 综合色图,成人综合网| 国产精品一区二区校花| 九九九九亚洲| 亚洲色图国产另类| 五月综合久久| 思思热在线cao| 九九九九九九九九九国产精品 | 九热大香蕉| 在线播放成人网站| 欧美午夜视频免费观看| 精品日日人妻| 精品一区二区三区四区外站| 好吊妞转入那个网| 色噜噜精品一区二区三| 啊啊啊啊啊在线| 智利AV在线网| 久久e6只有精品| 成人综合久久精品色婷婷| а√天堂资源官网在线资源| 精品国产乱码久久久久久免费| 久久综合中文国产| 东京热男人的天堂网| 日本女优在线视频福利| 男插女青青影院| 亚洲综合在线91| 91nbbbbbb| 久久人人爽爽爽人久久久| 91日本在线观看| 无码WWW免费视频网站| 欧美精品精品一区二区| 亚洲女人91| 日韩丨制服丨中文|在线| 亚洲综合影片| 麻豆天美国美国产| 午夜男女爽爽爽在线视频| 国产一级特黄大片处女| 女性喷水高潮在线观看| 校园春色亚洲色图| 变态另类专区| 精品二区久久| 日韩熟女视频二区| 久久久久久久久久精| 91撸色网 玖玖网 欧美| 中文字幕精品人妻丝袜| 神马精品视频| 殴美,日韩国产伦精品| 性爱综合网| 91超级碰| 超碰av在线| 国产成年精品高清在线观看91| 视频一区二区免费在线| 九九热九九| 97色色色| 3PAV乱伦视频| 亚洲日韩av专区无码| 国产捆绑一区| 国产 亚洲 一二三四| 91精品人妻偷情| 久久这里只精品免费福利| 69国产对白刺激| 日韩av性爱在线播放| 日韩无码一级黄色av片| 国产一区二区成人av在线播放| 色综合国产在线观看| 免费αV在线视频| 91影库| a级成人毛片免费视频高清| 亚洲国产一级精品毛一级精品看免费视频 | 99久久精品无码一区二区毛片免费 | 国模精品一区二区三区苹果色戒| 亚洲福利中文字幕在线| 超碰久热| 东京热,男人的天堂| avav青青草久久夜| 高清孕妇孕交 交| 亚洲欧美日韩偷拍色图| 亚洲乱色熟女一区| 黄色小视频日本txt| 婬女免费一二三区A片| 26uuu欧美| 欧中日成人免费影视| 亚洲精品一卡二卡三卡福利视频网站 | 亚洲色图欧美一区二区不卡| 操逼逼一区视频| 国产精品一级毛片不卡视| 国产又操| 九九久久首页| 天天草AV| 亚洲天堂男人的天堂| 丰满人妻一区二区三区性色| 少妇高潮对白在线观看| 精品一区二区啪啪啪| 久草婷婷| 91白虎| 天天躁日日躁成人字幕aⅴ| 强奸乱伦大香蕉网| 久久久com| 伊人久久亚洲色欲综合网站 | 亚洲无码太久| 另类视频在线| 青青草大香蕉在线视频| 欧日韩一二三f区| 国产不良强奸视频免费看| 婷婷AV一区二区三区| 91是天天| 欧美在线亚洲| 岛国大片国产| 五月天婷婷欧美三区| 97在线观视频免费观看| 丰满人妻一区二区三区蜜桃视频| 一本大道不卡一二三区| 激情综合97| 2019亚洲男人天堂| 亚洲网站一区二区在线| 99熟女| 日日做夜狠狠爱欧美黑人| 国产AV中文| 日韩性爱再线视频| 日本 免费 一区二区三区 久久香蕉| 91欧美少妇| www亚洲免费| 欧美色三级片91| 久久精品无码熟妇一区二区三区视频导航 | 欧美se综合| 国产强奸超碰AV| 加勒比日本在线| 久久精品国产Aⅴ| 久热超碰| 深夜激情| 一个人免费HD91视频| 九九九久久久久| 精品人妻一区二区三区四区不卡在| 爆操无码| 亚洲色图第四色| 操操逼视频| 一区二区三区四区五区高清无码永久视频 | 亚洲一卡二卡在线免费| 国产伦精品免编号公布| 九九九九九九九九九国产精品 | 欧美综合在线91| 中日韩免费看男女操逼大全| 亚洲图片欧美日韩| 亚洲 欧美 色图| 久热久| 精品人妻少妇| 色五月婷婷在线| 久久线上视频免费看| 久操大香蕉| 快播电影网日韩新片| 久久人人爽人人爽人人片Ⅴ| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 一级特黄aaa大片在线观看成人一级片在线观看| 色综合一区二区三巨| 91 天天综合| 五月天综合网| 火箭成精品视频884必出精品| 少妇超碰在线| 9久精品| 欧美色997| 97人人夜夜精品视频| 精品美女少妇一区二区三区| 视频黄色国产一级| 亚洲九九视频在线观看| 国产精品久久久鸭无码的功能| 亚洲天堂久久| 日本操BAV| 2017,超碰| 夜夜爽爽爽| 国产精品一区二区a| 97视频在线观看高清资源| 青娱乐欧美激情一区二区 | 欧美十八禁在线看| 中文 人妻 制服| 欧美成人精品一区二区三区| 日韩成人在线性爱视频| 美女91av| 日本三级韩国三级99| a级免费在线观看| 歐美性天天| 91|九色|国产熟女| 国产色产精品在线观看| 熟女AV一区| 一区二区视频在线播放| 干妹子| 1024亚洲中文字幕久在线看片你懂的 | 中文字幕成人理论在线| 丝袜AV一区二区三区| 久久一二三级一一一| 亚洲成人无码影院| 天天狂操夜夜狂日| 91网18| 午夜丁香婷婷| 色操逼网| 中文字幕三四五区| 77国产精品| 久久午夜伦| 欧美十八禁导航成人| 欧洲综合色图| 色爽——AV| 久久久亚洲精品电影免费看| 欧美强奸乱能| 91无码西班牙视频在线| WWW美腿丝袜香蕉中文| 午夜精品一区二区三区三上悠亚| 国产一在线观看| 熟妇无码视频三区| 国产乱弄免费在线视频。| 区二区亚洲婷| www.久久| 另类 日韩 熟女| 久草尤物| 啊啊啊啊啊啊啊啊在线观看| 日韩色女精品| 九九英色视频| 久久极品伊人| 日本韩欧美在线播放a| 日韩无码精品综合久久| 精品黄色电影| 欧美色图另类图片| 久久精品中文字幕女同| 中文字幕88av在线| 中文字幕av色| 人妻少妇色综合| 极品美女福利在线观看| 国产精品盗摄 偷窥盗摄| 青草伊人久久| 色 亚洲 91| 黄总AV色图| 97 亚洲 日韩 欧美 在线| 丁香五月天堂| 国模吧 一区二区三区| 国产一区二区a毛片| 国产亚洲精品一区二区三区| 干少妇视频| 蜜臀99久久国产| 九九九只有精品| 久久久成人精品| 欧美亚洲成人在线一区二区三区| 中文字幕av久久爽Av| 久久这里都是精品| 97天天爽| 天天肏美女| 好淫网一二三视区| 日韩av女优在线免费一区| 天天操夜夜操| 91爽啪| 116美女午夜| 97 亚洲 日韩 欧美 在线| 97人肏| 91久青| 日本丝袜美腿人妻九九| 台湾佬中文娱乐自偷自拍| 超碰av人人人| 欧美日韩m| 麻豆国产av网| 鸥美插入视频| 骚人妻少妇视频| 俺也射| 天天操妹子| 超碰九7| 九九九精品成人免费视频小说| 亚洲色婷婷久久91| 99e久久国产精品| 国产二区视频在线观看电影| h4610国产人妻| 日韩激情啪啪| 色色操| 91九九九馒头| 干B| 玖色av| 91丨人妻丨国产丨丝袜| 日韩欧美大片免费高清啪啪| 成人乱人伦一区二区| 午夜影美女日鸡鸡天天视频国产| 亚洲精品美女久久久久久久久| 亚洲色啪| 歐美一級亂黃99在綫精品| 综合天天网| 日韩专区久久久| 色97干| 成人一道本免费视频| 日美免费黄片| 午夜精品一区二区三区三上悠亚| 亚洲码和欧洲精品激情系列| 色眯眯av| 欧美日韩资源| 91东京热男人的天堂| 中文字幕亚洲热播人妻| 国产激情久久久| 欧美成不卡网| 亚洲精品 欧美精品| 亚洲小说视频| 亚洲av国产av综合av卡| 色综合网1| 日本一区二区三区欧美日韩中文字幕| SS久久| 亚洲男人的天堂va亚洲男人社| 极品欧美一区二区三区| 婷婷五月天激情网| 成 人 影视 一区 二区 三区 四区 | 超碰一区二区| 97久久超碰| 性色av网站| 国产精品经典一卡久久久 | 夜间福利片1000无码| 长长久久免费视频| 国产欧美后入| 午夜美女福利视频| 极品白嫩美女白浆成人福利在线看| 91狠狠综合久久久久久| 欧洲自拍第一页| 91久久免费视频互動交流 | 蜜臀无码视频在线观看| 91日本在线观看| 欧美色图下一页| 97碰| 99ri视频| 日本最新1区2区3区| CCYY草草影院地址入口| 五月天丁香| 久草线上视频免费看| 亚洲欧美日韩制服另类| 激情婷婷五月天| 伊人久久亚洲色欲综合网站| 乱性AV| 99热综合在线| 欧色网址| 亚洲成?V人片在线观看福利| 熟女网站最新| 中文字幕第9页萱萱影音先锋| 五月婷婷大香蕉| 久久9精品网站| 欧美aaaaaaa| 啊啊啊好舒服好爽啊啊啊视频| 91天天综合日韩欧美| 亚洲精品久久久久久久蜜桃臀| 性交一区二区在线播放| 亚洲密乳AV| 1024亚洲中文字幕久在线看片你懂的| 日日骚一区二区三区| 午夜久久无码1000合集| 亚洲宗合网| 色色色色日本| 日本男人插女人的逼黄色| 久久亚洲中文字幕视频| 女人妻一区| 午夜啪| 嗯嗯嗯啊啊啊操的我好爽| 久久大黄片| 69AV女优男人的天堂| 亚洲男人天堂AV| 曰韩精品九九无码| 精品午夜福利| 亚洲国产欧美日韩人妻日中文| 精品视频在线观看| 超碰久久中文| 中国操逼无码| 加勒比AV网| 久久久久人妻二区精品叶可怜| 人妻在线大香蕉| 精品一区二区综合熟妇| 亚洲天堂电影网| 国产精品视频精品一二| 日产精品久久久一区二区| 91久久99久久91熟女精品| 久久久偷拍| 啊啊啊啊视频免费| se吧提供91精品国产91久久久久久| 中文字幕免费观看| 先锋色眉乱伦资源| 啊啊啊啊在线播放| 超碰免费在线| 日韩av无码网站| 精产国品一区二三产品| 最新三级网址| 天天大干大香蕉| 日本女人操逼| 啊啊啊好想要| 亚洲永久永久永久永久一级一级一级精品| 无码高清操逼网址| 97视频在线免费播放| 色色丁香| 人人弄人人摸| 五月天亚洲网| 男人天堂久久精品| 欧美日韩黄片精品在线| 97伦乱| 老鸭窝亚洲毛片| 国产对白刺激视频| 熟女字幕| 日本 情色 1区| 殴美日韩m| 极品白嫩美女白浆成人福利在线看| 亚州综| 老女人碰碰在线碰碰视频| a在线视频免费观看| 亚洲中文字幕在线视频一区二区| 久久99草| 夜夜嗨一区二区| 18啪啪手机免费性爱| 大香交伊人网| 男人兔费天堂| 在线播放一级无码视频| 99视频自拍区| 欧美日韩人人早| 国产亚洲国产超碰| 欧洲综合无码| 天天爱天天操| 91超碰碰在线| 欧美嗯啊……在线观看视频免费| 精品成人动漫一区二区| 美女啊啊啊啊啊啊| 91成人久久| 日韩精品人妻中文字幕有码午| 爱av免费| 一区二区三区在线美女| 日韩一卡二卡三卡| 91少妇香蕉久久精品| 国产不卡片| 久操热| 园内精品自拍视频在线播放| 97欧美视频| 91热热色| 精品人妻一二三四区视频| 久久综合久久综合人久久夜精品| 国产福利第一视频| 欧美一级久久久久久久大片动画| 久久青青草在线视频| 伊人网在线点播| 嗯嗯啊啊好大好爽| 亚洲AV资源| 日韩美一区| 激情开心五月天| 免费操逼视频下载| 色五天伊人| 伊人五月天婷婷| 屁股久久久久久| 久久久555| 亚洲精品黄码久久久久| 2019亚洲男人天堂| 久久大精品乱码视频人妻熟女| 99国产精品在线观看| 91狠| 六九九九| 日韩三级一区| 亚洲激情网一二三四区| 亚洲高清在线| 狠狠色色| 久久免费精彩视频| 91日韩在线| 99在线精品观看99| 日本免费亚洲欧美| 在线99热| 成片免费观看视频大全| 香蕉久久国产AV一区二区| 免费毛片在线播放| 久综合网| 亚洲va综合va国产va中文| 开心婷婷五月| 日韩精品一区二区三区四虎影视| 99色在线观看| 久热无码| 天美精品av| 午夜激情床戏激情| 不卡码视频| 欧美aⅴ99久久黑人专区| 亚洲美女 晚间男人天堂 | 肏逼视频日本| 99亚洲国产精品色一区二区三区| 国内精品嫩模A∨私拍小视频| 亚洲无码精品AV久久久| 国产精品麻豆免费视频| 岛国黄色短视频| 亚洲一区二区三区欧美日韩| 九九无码视频|