網(wǎng)站域名包括重慶男科醫(yī)院哪家好
鶴壁市浩天電氣有限公司
2026/01/24 10:33:57
網(wǎng)站域名包括,重慶男科醫(yī)院哪家好,WordPress全屏輪播圖,wordpress登錄框透明1? 跨平臺(tái)架構(gòu)目標(biāo)#xff08;Cross-Platform Architecture Goals#xff09;
在設(shè)計(jì)跨平臺(tái)系統(tǒng)時(shí)#xff0c;目標(biāo)包括#xff1a;
充分利用各個(gè)平臺(tái)特性 不僅考慮功能#xff0c;還要利用不同平臺(tái)的性能優(yōu)化和特性。 關(guān)注編譯器特性 利用編譯器提供的優(yōu)化、警告、概念…1? 跨平臺(tái)架構(gòu)目標(biāo)Cross-Platform Architecture Goals在設(shè)計(jì)跨平臺(tái)系統(tǒng)時(shí)目標(biāo)包括充分利用各個(gè)平臺(tái)特性不僅考慮功能還要利用不同平臺(tái)的性能優(yōu)化和特性。關(guān)注編譯器特性利用編譯器提供的優(yōu)化、警告、概念concepts等功能。最小化樣板代碼boilerplate避免重復(fù)寫(xiě)大量初始化、模板或輔助函數(shù)。減少冗余代碼例如重復(fù)實(shí)現(xiàn)同一邏輯或類型特化。盡量不修改已有代碼保證已有功能穩(wěn)定減少回歸風(fēng)險(xiǎn)。盡量減少預(yù)處理宏preprocessor macros宏容易引入不可控的副作用和調(diào)試?yán)щy應(yīng)優(yōu)先用模板、概念或constexpr替代??偨Y(jié)目標(biāo)是寫(xiě)高效、可維護(hù)、可擴(kuò)展的跨平臺(tái)代碼。2? 設(shè)計(jì)方案The Design示例四元數(shù)類Quaternion族這是一個(gè)大型項(xiàng)目中的例子用于說(shuō)明跨平臺(tái)設(shè)計(jì)。項(xiàng)目構(gòu)建問(wèn)題不同平臺(tái)可能需要包含不同的頭文件。概念層次Concept Hierarchies使用 C20 概念concept來(lái)定義類型約束和接口契約。類和函數(shù)設(shè)計(jì)通過(guò)模板和泛型編程減少重復(fù)代碼。提供統(tǒng)一接口屏蔽平臺(tái)差異。核心思想在不同平臺(tái)上復(fù)用核心邏輯同時(shí)對(duì)外提供統(tǒng)一接口。3? 開(kāi)放–封閉原則OCP: Open–Closed Principle定義對(duì)擴(kuò)展開(kāi)放對(duì)修改封閉。系統(tǒng)應(yīng)允許通過(guò)添加新代碼實(shí)現(xiàn)新功能而不是修改已有代碼。在 C 中實(shí)現(xiàn)方式委托式多態(tài)delegated polymorphism使用虛函數(shù)、接口類、模板或概念將功能擴(kuò)展委托給新類或函數(shù)而不修改原有類。好處避免“級(jí)聯(lián)修改”cascade of changes。提高代碼可維護(hù)性和穩(wěn)定性。引用“Since programs that conform to the open–closed principle are changed by adding new code, rather than by changing existing code, they do not experience the cascade of changes exhibited by non-conforming programs.”— Robert C. Martin (1996)小結(jié)跨平臺(tái)架構(gòu)設(shè)計(jì)目標(biāo)高性能、低冗余、低樣板、易維護(hù)。設(shè)計(jì)方法使用模板、概念、抽象類和統(tǒng)一接口屏蔽平臺(tái)差異。遵守 OCP通過(guò)擴(kuò)展而不是修改已有代碼實(shí)現(xiàn)新功能。利用多態(tài)、概念和模板實(shí)現(xiàn)委托式擴(kuò)展。例子繪制圖形 — C 風(fēng)格未應(yīng)用開(kāi)放–封閉原則 OCP1? 數(shù)據(jù)結(jié)構(gòu)Shape Data在 C 語(yǔ)言中為了表示不同類型的形狀通常會(huì)使用enum和structtypedefenum{circle,square}shape_type;shape_type枚舉定義了形狀類型圓形circle或正方形square。typedefstruct{shape_type type;intradius;}circle_shape;typedefstruct{shape_type type;intside_length;}square_shape;circle_shape結(jié)構(gòu)體包含type形狀類型必須是circleradius半徑square_shape結(jié)構(gòu)體包含type形狀類型必須是squareside_length邊長(zhǎng)問(wèn)題點(diǎn)每個(gè)形狀都有自己的 struct需要手動(dòng)管理。數(shù)據(jù)和行為繪制函數(shù)是分開(kāi)的缺乏封裝。2? 繪圖函數(shù)Drawing Functions針對(duì)每種形狀單獨(dú)實(shí)現(xiàn)繪制函數(shù)voiddraw_circle(circle_shape*c);voiddraw_square(square_shape*s);draw_circle專門(mén)繪制圓形draw_square專門(mén)繪制正方形這意味著每添加一種新形狀都需要新增函數(shù)。3? 繪制多個(gè)形狀draw_shapes 函數(shù)voiddraw_shapes(shape**shapes,intn){inti;for(i0;in;i){switch(shapes[i]-type){casecircle:draw_circle((circle_shape*)(shapes[i]));break;casesquare:draw_square((square_shape*)(shapes[i]));break;}}}shapes是一個(gè)指向形狀的指針數(shù)組。使用switch判斷形狀類型如果是circle調(diào)用draw_circle如果是square調(diào)用draw_square使用強(qiáng)制類型轉(zhuǎn)換cast將shape*轉(zhuǎn)為具體類型指針。4? C 風(fēng)格設(shè)計(jì)的問(wèn)題點(diǎn)違反開(kāi)放–封閉原則OCP如果要新增形狀比如三角形必須修改draw_shapes函數(shù)違反“封閉修改”原則。類型安全問(wèn)題使用void*或強(qiáng)制類型轉(zhuǎn)換容易出錯(cuò)。編譯器無(wú)法檢查類型正確性。行為分離繪制邏輯在外部函數(shù)中而數(shù)據(jù)結(jié)構(gòu)只包含數(shù)據(jù)缺乏封裝??删S護(hù)性差每新增形狀需要修改多個(gè)地方枚舉、結(jié)構(gòu)體、繪圖函數(shù)、switch-case。總結(jié)這是典型的 C 風(fēng)格實(shí)現(xiàn)以數(shù)據(jù)驅(qū)動(dòng)類型判斷enum switch來(lái)實(shí)現(xiàn)多態(tài)。問(wèn)題在于擴(kuò)展困難添加新形狀需要修改已有函數(shù)類型不安全行為與數(shù)據(jù)分離在 C 中OCP 可以通過(guò)繼承 虛函數(shù)或概念 模板來(lái)改進(jìn)避免修改已有代碼只通過(guò)擴(kuò)展新類或新模板實(shí)現(xiàn)新的形狀。例子繪制圖形 — C 多態(tài)方式Polymorphic C Way1? 形狀類Shape Classes抽象基類shapeclassshape{public:virtualvoiddraw()const0;};shape是一個(gè)抽象基類abstract class。包含純虛函數(shù)draw()表示所有形狀都必須實(shí)現(xiàn)繪制方法。封裝與多態(tài)數(shù)據(jù)和行為封裝在類里。用戶無(wú)需關(guān)心具體形狀的實(shí)現(xiàn)。派生類circleclasscircle:publicshape{intradius;public:voiddraw()constoverride;};circle繼承自shape包含私有數(shù)據(jù)成員radius重寫(xiě)draw()方法實(shí)現(xiàn)圓形繪制邏輯派生類squareclasssquare:publicshape{intside_length;public:voiddraw()constoverride;};square繼承自shape包含私有數(shù)據(jù)成員side_length重寫(xiě)draw()方法實(shí)現(xiàn)正方形繪制邏輯2? 繪制函數(shù)Draw Function#includeshape.hvoiddraw_shapes(std::vectorshape*shapes){for(autoconst*s:shapes){s-draw();}}shapes是一個(gè)指向shape*的向量核心點(diǎn)通過(guò)虛函數(shù)機(jī)制virtual function調(diào)用draw()方法實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)runtime polymorphism不需要switch-case或類型轉(zhuǎn)換新增形狀只需要新建派生類重寫(xiě)draw()方法不需要修改draw_shapes函數(shù)3? 多態(tài) C 風(fēng)格的優(yōu)點(diǎn)符合開(kāi)放–封閉原則OCPdraw_shapes函數(shù)無(wú)需修改支持新形狀擴(kuò)展。類型安全無(wú)需強(qiáng)制類型轉(zhuǎn)換編譯器檢查類型。封裝數(shù)據(jù)和行為每個(gè)形狀類封裝自己的數(shù)據(jù)和繪制邏輯。易維護(hù)擴(kuò)展新形狀時(shí)只需增加新類不破壞已有代碼。可復(fù)用性和可讀性強(qiáng)用戶只使用基類接口shape*無(wú)需了解具體實(shí)現(xiàn)??偨Y(jié)特性C 風(fēng)格C 多態(tài)風(fēng)格數(shù)據(jù)與行為分離封裝在類里類型安全不安全需要 cast安全虛函數(shù)多態(tài)擴(kuò)展性需修改 switch-case只需新增類遵守 OCP否是可維護(hù)性差好總結(jié)一句話C 多態(tài)方式通過(guò)繼承與虛函數(shù)將“類型判斷 繪制邏輯”隱藏在類內(nèi)部實(shí)現(xiàn)了開(kāi)放–封閉原則和更好的封裝。1? 原始開(kāi)放–封閉原則Original OCP引用 Bertrand Meyer1988的定義模塊應(yīng)既“封閉”又“開(kāi)放”封閉Closed一旦模塊的服務(wù)對(duì)外公開(kāi)客戶端依賴這些服務(wù)進(jìn)行開(kāi)發(fā)時(shí)模塊的現(xiàn)有功能不應(yīng)受到新服務(wù)引入的影響。換句話說(shuō)已有模塊接口穩(wěn)定現(xiàn)有客戶代碼不受影響。開(kāi)放Open模塊應(yīng)能擴(kuò)展新功能以支持未來(lái)的需求而無(wú)需修改已有代碼。因?yàn)槲覀儾豢赡芤婚_(kāi)始就實(shí)現(xiàn)所有客戶端可能需要的功能。2? OCP 在 C 中的體現(xiàn)在 C 中OCP 可以分為弱原則Weak OCP和強(qiáng)原則Strong OCP(1) 無(wú) OCPNo OCP行為必須修改已有代碼來(lái)添加新功能??蛻舳舜a需要根據(jù)修改做出相應(yīng)變化。問(wèn)題現(xiàn)有模塊不穩(wěn)定維護(hù)成本高。修改模塊會(huì)引發(fā)連鎖修改。(2) 弱 OCPWeak OCP行為添加新功能時(shí)仍然需要修改已有代碼但現(xiàn)有接口和行為保持不變。需要重新編譯受影響的模塊。特點(diǎn)接口穩(wěn)定但實(shí)現(xiàn)需要改動(dòng)??蛻舳艘蕾嚨慕涌诓蛔兊K的代碼仍需維護(hù)。(3) 強(qiáng) OCPStrong OCP行為添加新功能完全無(wú)需修改已有代碼。不影響現(xiàn)有模塊的編譯和客戶端代碼。實(shí)現(xiàn)方式通過(guò)多態(tài)polymorphism或委托delegation來(lái)擴(kuò)展功能。保持模塊接口和實(shí)現(xiàn)的獨(dú)立性。優(yōu)點(diǎn)最大化模塊穩(wěn)定性和可維護(hù)性。支持真正的“開(kāi)閉”即模塊對(duì)擴(kuò)展開(kāi)放對(duì)修改封閉。3? 對(duì)比總結(jié)類型修改已有代碼客戶端影響編譯影響無(wú) OCP需要修改客戶端需改動(dòng)是弱 OCP需要修改客戶端無(wú)需改動(dòng)是強(qiáng) OCP不修改客戶端無(wú)需改動(dòng)否關(guān)鍵點(diǎn)封閉Closed已有模塊穩(wěn)定客戶端依賴的接口不變。開(kāi)放Open模塊可以擴(kuò)展新功能不修改已有模塊代碼。C 實(shí)踐強(qiáng) OCP 通常通過(guò)虛函數(shù)、多態(tài)、接口抽象實(shí)現(xiàn)。弱 OCP 可能仍需修改實(shí)現(xiàn)但保證接口穩(wěn)定??偨Y(jié)一句話OCP 的核心是“擴(kuò)展無(wú)需修改”。強(qiáng) OCP 通過(guò)抽象和多態(tài)實(shí)現(xiàn)弱 OCP則保證接口不變但實(shí)現(xiàn)可修改。1? 架構(gòu)設(shè)計(jì)指導(dǎo)原則Architecture Guidelines設(shè)計(jì)非常接近Bertrand Meyer的原始設(shè)想不局限于傳統(tǒng)面向?qū)ο驩OP數(shù)據(jù)與函數(shù)可以分離。添加新平臺(tái)不應(yīng)影響已實(shí)現(xiàn)的平臺(tái)新增對(duì)某個(gè)平臺(tái)的支持時(shí)已有平臺(tái)代碼無(wú)需修改。添加功能的版本或修訂不應(yīng)影響已實(shí)現(xiàn)的版本擴(kuò)展功能版本時(shí)已有版本仍然保持穩(wěn)定。2? 平臺(tái)Platform定義平臺(tái)特定的功能集feature set每個(gè)平臺(tái)包含實(shí)現(xiàn)同一功能但針對(duì)不同機(jī)器架構(gòu)的實(shí)現(xiàn)。功能Feature抽象的功能單元需要根據(jù)目標(biāo)機(jī)器架構(gòu)實(shí)現(xiàn)不同版本。硬件相關(guān)CPU 架構(gòu)x86, ARMSIMD 指令集SSE, SSE2, NeonDMA 控制器、GPIO 模塊等軟件相關(guān)操作系統(tǒng)Windows, Linux圖形 APIDirectX, OpenGL注意功能不一定完全正交例如x86 SSEDirectX Windows功能之間可能存在耦合關(guān)系。3? 目錄和文件結(jié)構(gòu)(1) Flat 結(jié)構(gòu)平鋪plt/simd Simd.h Neon32.h Sse.h Sse2.h ... plt/math Quat.h Quat_Common.h Quat_Neon32.h Quat_Sse.h Quat_Sse2.h ...所有文件平鋪在同一目錄下。易于查找但文件數(shù)量多時(shí)可能雜亂。(2) Deep 結(jié)構(gòu)分層plt/simd Simd.h Neon32.h Sse.h Sse2.h ... plt/math Quat.h Common/ Quat_Common.h Vec_Common.h Mtx_Common.h ... Neon32/ Quat_Neon32.h Vec_Neon32.h Mtx_Neon32.h ...使用子目錄按功能或平臺(tái)分類。優(yōu)點(diǎn)文件結(jié)構(gòu)清晰便于管理平臺(tái)相關(guān)實(shí)現(xiàn)。避免命名沖突。缺點(diǎn)包含路徑較長(zhǎng)需要宏或別名輔助引用。4? 頭文件包含策略每個(gè)功能Feature都有自己的頭文件定義公共接口或宏。頭文件負(fù)責(zé)包含平臺(tái)特定的實(shí)現(xiàn)。使用預(yù)處理宏自動(dòng)生成包含的文件名例如INCLUDE_SIMD(Quat)會(huì)展開(kāi)為Quat_SSE2.h這樣用戶只需寫(xiě)INCLUDE_SIMD(Quat)無(wú)需關(guān)心平臺(tái)實(shí)現(xiàn)。5? 頭文件包含宏示例#defineINCLUDE_PLT(Feature,File)INCLUDE_BUILD_FILENAME(Feature,File)#defineINCLUDE_PLT_FEATURE(Feature)INCLUDE_STRINGIZE(Feature.h)#defineINCLUDE_BUILD_FILENAME(Feature,File)INCLUDE_STRINGIZE(File##_##Feature.h)#defineINCLUDE_STRINGIZE(String)#String#defineINCLUDE_SIMD(File)INCLUDE_PLT(PLT_SIMD,File)INCLUDE_STRINGIZE(String)將宏參數(shù)轉(zhuǎn)換為字符串。INCLUDE_BUILD_FILENAME(Feature, File)拼接文件名例如File_Feature.h。INCLUDE_PLT(Feature, File)生成平臺(tái)相關(guān)的完整文件名。INCLUDE_SIMD(File)針對(duì) SIMD 功能自動(dòng)選擇當(dāng)前平臺(tái)的 SIMD 文件。總結(jié)通過(guò)宏封裝平臺(tái)相關(guān)實(shí)現(xiàn)保持代碼抽象。用戶只需要關(guān)注功能接口如Quat無(wú)需關(guān)心平臺(tái)差異。符合開(kāi)放–封閉原則OCP添加新平臺(tái)無(wú)需修改現(xiàn)有代碼。1? 創(chuàng)建功能Creating a Feature定義功能在構(gòu)建系統(tǒng)build system中定義功能宏。創(chuàng)建頭文件為每個(gè)功能創(chuàng)建一個(gè)公共頭文件feature header。創(chuàng)建實(shí)現(xiàn)文件為每種特定平臺(tái)或?qū)崿F(xiàn)版本創(chuàng)建獨(dú)立的頭文件。目的是保持功能接口統(tǒng)一而實(shí)現(xiàn)可以隨平臺(tái)變化而變化。2? SIMD 功能在構(gòu)建系統(tǒng)中的配置在工具鏈文件中設(shè)置平臺(tái)宏set(PLT_SIMD Common)在公共項(xiàng)目中將宏加入編譯預(yù)處理定義add_compile_definitions( PLT_SIMD${PLT_SIMD} )這樣在編譯時(shí)代碼可以根據(jù)PLT_SIMD的值自動(dòng)選擇平臺(tái)特定實(shí)現(xiàn)。3?Simd.hSIMD 功能頭文件#if!defined(PLT_SIMD)#errorYou must define PLT_SIMD.#endif#defineINCLUDE_SIMD(File)INCLUDE_PLT(PLT_SIMD,File)#includeINCLUDE_PLT_LOCAL(PLT_SIMD)功能說(shuō)明檢查是否定義PLT_SIMD如果沒(méi)有定義則報(bào)錯(cuò)。定義宏INCLUDE_SIMD(File)用于包含平臺(tái)特定實(shí)現(xiàn)。根據(jù)當(dāng)前平臺(tái)包含相應(yīng)的 SIMD 文件。4?Simd_Common.h通用 SIMD 頭文件namespaceplt::simd{structCommon{};}提供一個(gè)空的通用結(jié)構(gòu)體用于標(biāo)記或作為概念實(shí)現(xiàn)的基礎(chǔ)。平臺(tái)特定實(shí)現(xiàn)可繼承或擴(kuò)展此結(jié)構(gòu)體。5? 四元數(shù)的數(shù)學(xué)定義Quaternions, Mathematically Speaking四元數(shù)Quaternionq w x i y j z k q w x i y j z kqwxiyjzk基本單位i 2 j 2 k 2 i j k ? 1 i^2 j^2 k^2 i j k -1i2j2k2ijk?1乘法規(guī)則i j k ? j i , j k i ? k j , k i j ? i k i j k - j i, quad j k i - k j, quad k i j - i kijk?ji,jki?kj,kij?ik5.1 四元數(shù)的運(yùn)算加法( a w a x i a y j a z k ) ( b w b x i b y j b z k ) ( a w b w ) ( a x b x ) i ( a y b y ) j ( a z b z ) k (a_w a_x i a_y j a_z k) (b_w b_x i b_y j b_z k) (a_w b_w) (a_x b_x)i (a_y b_y)j (a_z b_z)k(aw?ax?iay?jaz?k)(bw?bx?iby?jbz?k)(aw?bw?)(ax?bx?)i(ay?by?)j(az?bz?)k乘法( a w a x i a y j a z k ) ( b w b x i b y j b z k ) ( a w b w ? a x b x ? a y b y ? a z b z ) ( a w b x a x b w a y b z ? a z b y ) i ( a w b y ? a x b z a y b w a z b x ) j ( a w b z a x b y ? a y b x a z b w ) k egin{aligned} (a_w a_x i a_y j a_z k)(b_w b_x i b_y j b_z k) (a_w b_w - a_x b_x - a_y b_y - a_z b_z) (a_w b_x a_x b_w a_y b_z - a_z b_y)i (a_w b_y - a_x b_z a_y b_w a_z b_x)j (a_w b_z a_x b_y - a_y b_x a_z b_w)k end{aligned}(aw?ax?iay?jaz?k)(bw?bx?iby?jbz?k)?(aw?bw??ax?bx??ay?by??az?bz?)?(aw?bx?ax?bw?ay?bz??az?by?)i?(aw?by??ax?bz?ay?bw?az?bx?)j?(aw?bz?ax?by??ay?bx?az?bw?)k?共軛Conjugateq ? w ? x i ? y j ? z k q^* w - x i - y j - z kq?w?xi?yj?zk點(diǎn)積Dot Producta ? b a w b w a x b x a y b y a z b z a cdot b a_w b_w a_x b_x a_y b_y a_z b_za?baw?bw?ax?bx?ay?by?az?bz?模Norm∣ q ∣ q ? q w 2 x 2 y 2 z 2 |q| sqrt{q cdot q} sqrt{w^2 x^2 y^2 z^2}∣q∣q?q?w2x2y2z2?乘法逆元Multiplicative Inverseq ? 1 q ? q ? q q^{-1} frac{q^*}{q cdot q}q?1q?qq??除法a b a b ? 1 a b ? b ? b frac{a} a b^{-1} frac{a b^*}{b cdot b}ba?ab?1b?bab??6? 四元數(shù)概念在 C20 中的映射數(shù)學(xué)定義四元數(shù)由數(shù)據(jù)與運(yùn)算定義。C20 概念Concept定義四元數(shù)由數(shù)據(jù)成員定義運(yùn)算可基于概念實(shí)現(xiàn)。實(shí)現(xiàn)策略通用實(shí)現(xiàn)依賴于概念定義。平臺(tái)優(yōu)化實(shí)現(xiàn)需符合概念并可替換通用實(shí)現(xiàn)。總結(jié)概念Concept定義了接口和數(shù)據(jù)結(jié)構(gòu)約束。實(shí)現(xiàn)可以依賴概念進(jìn)行優(yōu)化和擴(kuò)展保證 OCP開(kāi)放–封閉原則。1? Quaternion 概念C20 ConcepttemplatetypenameQconceptQuaternionrequires(Q q){typenameQ::Scalar;ArithmetictypenameQ::Scalar;{q.w()}-std::same_astypenameQ::Scalar;{q.x()}-std::same_astypenameQ::Scalar;{q.y()}-std::same_astypenameQ::Scalar;{q.z()}-std::same_astypenameQ::Scalar;};解析Q::Scalar表示四元數(shù)元素的標(biāo)量類型例如float或double。Arithmetictypename Q::Scalar確保標(biāo)量類型是算術(shù)類型。{ q.w() } - std::same_astypename Q::Scalar等語(yǔ)句要求Q提供訪問(wèn)四元數(shù)各分量的函數(shù)返回類型為標(biāo)量類型。對(duì)應(yīng)數(shù)學(xué)上的四元數(shù)q w x i y j z k q w x i y j z kqwxiyjzk其中w , x , y , z w, x, y, zw,x,y,z對(duì)應(yīng)q.w(), q.x(), q.y(), q.z()。2? 支持性概念Supporting ConceptsArithmetictemplatetypenameTconceptArithmeticstd::is_arithmetic_vT;限定標(biāo)量類型必須是算術(shù)類型整數(shù)或浮點(diǎn)數(shù)。MutuallyArithmetictemplatetypenameT,typenameUconceptMutuallyArithmeticrequires(T t,U u){requiresArithmeticT;requiresArithmeticU;{tu};{t-u};{t*u};{t/u};};限定兩個(gè)類型間可以進(jìn)行算術(shù)運(yùn)算。用于實(shí)現(xiàn)四元數(shù)間或四元數(shù)與標(biāo)量間的運(yùn)算。3? 標(biāo)準(zhǔn)四元數(shù)類型聲明Standard Quaternion TypetemplatetypenameS,typenameIplt::simd::PLT_SIMDclassQuat{public:usingScalarS;private:Scalar w_,x_,y_,z_;// ... 構(gòu)造函數(shù)// ... 訪問(wèn)器};S標(biāo)量類型例如float、double。ISIMD 平臺(tái)選擇可用于優(yōu)化實(shí)現(xiàn)。私有成員w_, x_, y_, z_存儲(chǔ)四元數(shù)分量。4? 構(gòu)造函數(shù)ConstructorsQuat()default;Quat(Scalar w,Scalar x,Scalar y,Scalar z)noexcept(...):w_(w),x_(x),y_(y),z_(z){}Quat(Scalarw,Scalarx,Scalary,Scalarz)noexcept(...):w_(std::move(w)),x_(std::move(x)),y_(std::move(y)),z_(std::move(z)){}templateQuaternion Qrequiresstd::convertible_totypenameQ::Scalar,ScalarQuat(constQrhs)noexcept(...):Quat(Scalar{rhs.w()},Scalar{rhs.x()},Scalar{rhs.y()},Scalar{rhs.z()}){}支持拷貝構(gòu)造、移動(dòng)構(gòu)造、以及從其他符合Quaternion概念的四元數(shù)構(gòu)造。保證了類型安全與異常安全noexcept。5? 賦值操作符Assignment OperatortemplateQuaternion Qrequiresstd::convertible_totypenameQ::Scalar,ScalarQuatoperator(constQrhs)noexcept(...){w_Scalar{rhs.w()};x_Scalar{rhs.x()};y_Scalar{rhs.y()};z_Scalar{rhs.z()};return*this;}支持從任意滿足Quaternion概念的四元數(shù)賦值。自動(dòng)轉(zhuǎn)換標(biāo)量類型保證類型安全。6? 訪問(wèn)器AccessorsconstScalarw()constnoexcept{returnw_;}constScalarx()constnoexcept{returnx_;}constScalary()constnoexcept{returny_;}constScalarz()constnoexcept{returnz_;}提供對(duì)四元數(shù)各分量的只讀訪問(wèn)。與數(shù)學(xué)表示一一對(duì)應(yīng)q w x i y j z k q w x i y j z kqwxiyjzk7? 泛型操作實(shí)現(xiàn)General Operation Implementation使用表達(dá)式樹(shù)expression trees來(lái)實(shí)現(xiàn)操作??稍谌魏纹脚_(tái)上運(yùn)行。支持任何算術(shù)標(biāo)量類型。參數(shù)類型通過(guò)C20 Concepts限定保證接口一致性??偨Y(jié)C20 的概念使四元數(shù)實(shí)現(xiàn)可泛化、類型安全且可優(yōu)化。數(shù)學(xué)上的四元數(shù)運(yùn)算與 C 概念緊密對(duì)應(yīng)??筛鶕?jù) SIMD 或其他平臺(tái)進(jìn)行優(yōu)化實(shí)現(xiàn)而無(wú)需修改接口符合OCP開(kāi)放–封閉原則。1? 什么是表達(dá)式樹(shù)Expression Tree表達(dá)式樹(shù)是一種延遲求值lazy evaluation的表示方法將表達(dá)式拆分為節(jié)點(diǎn)每個(gè)節(jié)點(diǎn)表示運(yùn)算或操作數(shù)。示例表達(dá)式q 1 q 2 ? q 3 q_1 q_2 * q_3q1?q2??q3?對(duì)應(yīng)的表達(dá)式樹(shù)如下QuaternionAddition / q1 QuaternionMultiplication / q2 q3每個(gè)運(yùn)算符如、*在樹(shù)中生成一個(gè)節(jié)點(diǎn)操作數(shù)為葉子節(jié)點(diǎn)。2? C 實(shí)現(xiàn)運(yùn)算符和表達(dá)式節(jié)點(diǎn)2.1 加法運(yùn)算符Operator OverloadtemplateQuaternion QL,Quaternion QRinlineautooperator(constQLlhs,constQRrhs)noexcept-QuaternionAdditionQL,QR{returnQuaternionAddition(lhs,rhs);}該運(yùn)算符返回一個(gè)表達(dá)式節(jié)點(diǎn)QuaternionAddition。實(shí)際的加法操作不會(huì)立即執(zhí)行而是構(gòu)建表達(dá)式樹(shù)。2.2 四元數(shù)二元表達(dá)式基類templateQuaternion QL,Quaternion QRrequiresMutuallyArithmetictypenameQL::Scalar,typenameQR::ScalarclassQuaternionBinaryExpr:publicQuaternionExpr{usingSLtypenameQL::Scalar;usingSRtypenameQR::Scalar;public:usingScalartypenamestd::common_typeSL,SR::type;};通過(guò)MutuallyArithmetic確保兩邊標(biāo)量類型可以算術(shù)運(yùn)算。使用std::common_type推導(dǎo)結(jié)果標(biāo)量類型保證兼容不同標(biāo)量類型。2.3 加法表達(dá)式節(jié)點(diǎn)templateQuaternion QL,Quaternion QRclassQuaternionAddition:publicQuaternionBinaryExprQL,QR{QL l_;QR r_;public:usingScalartypenameQuaternionBinaryExprQL,QR::Scalar;QuaternionAddition(constQLlhs,constQRrhs)noexcept:l_(lhs),r_(rhs){}Scalarw()constnoexcept{returnl_.w()r_.w();}Scalarx()constnoexcept{returnl_.x()r_.x();}Scalary()constnoexcept{returnl_.y()r_.y();}Scalarz()constnoexcept{returnl_.z()r_.z();}};保存左右子表達(dá)式。訪問(wèn)函數(shù)w(), x(), y(), z()在訪問(wèn)時(shí)計(jì)算對(duì)應(yīng)分量的加法。延遲求值保證了表達(dá)式樹(shù)可以組合復(fù)雜運(yùn)算。3? 標(biāo)量函數(shù)示例templateQuaternion QL,Quaternion QRinlineautoDot(constQLlhs,constQRrhs)noexcept-QuaternionBinaryTypeQL,QR{returnlhs.w()*rhs.w()lhs.x()*rhs.x()lhs.y()*rhs.y()lhs.z()*rhs.z();}計(jì)算兩個(gè)四元數(shù)的點(diǎn)積a ? b a w b w a x b x a y b y a z b z a cdot b a_w b_w a_x b_x a_y b_y a_z b_za?baw?bw?ax?bx?ay?by?az?bz?返回標(biāo)量類型依賴于QuaternionBinaryType的推導(dǎo)。4? 通用實(shí)現(xiàn)Common ImplementationQuatfloateval(Quatfloata,Quatfloatb,Quatfloatc){return(a*bc)/(a-c);}所有四元數(shù)表達(dá)式基于概念Concepts和通用類實(shí)現(xiàn)??稍谌我馄脚_(tái)上運(yùn)行只要標(biāo)量類型在該平臺(tái)上支持。編譯器會(huì)根據(jù)表達(dá)式樹(shù)進(jìn)行優(yōu)化。優(yōu)點(diǎn)跨平臺(tái)統(tǒng)一實(shí)現(xiàn)。無(wú)需手動(dòng)展開(kāi)所有組合運(yùn)算??梢蕾嚲幾g器進(jìn)行自動(dòng)優(yōu)化。5? 針對(duì) ARM Neon 優(yōu)化5.1 構(gòu)建系統(tǒng)更新修改 SIMD 宏set(PLT_SIMD Neon32)可能需要設(shè)置編譯器標(biāo)志以啟用 Neon。5.2 Neon32 特性頭文件namespaceplt::simd{structNeon32:Common{};templatetypenameSIMDconceptNeon32Familystd::derived_fromSIMD,Neon32;}提供平臺(tái)標(biāo)識(shí)和概念約束。5.3 四元數(shù)類針對(duì) Neon32templateclassQuatfloat,plt::simd::Neon32{float32x4_t value_;// Neon 寄存器public:usingScalarfloat;Quat()default;Quat(Scalar w,Scalar x,Scalar y,Scalar z){floatvals[]{w,x,y,z};value_vld1q_f32(vals);// 加載到 Neon 寄存器}Scalarw()constnoexcept{returnvgetq_lane_f32(value_,0);}Scalarx()constnoexcept{returnvgetq_lane_f32(value_,1);}Scalary()constnoexcept{returnvgetq_lane_f32(value_,2);}Scalarz()constnoexcept{returnvgetq_lane_f32(value_,3);}};使用 Neon SIMD 寄存器存儲(chǔ)四元數(shù)。構(gòu)造函數(shù)和訪問(wèn)器直接操作 SIMD 寄存器。所有運(yùn)算仍可使用通用實(shí)現(xiàn)只是數(shù)據(jù)存儲(chǔ)和加載更快。6? 當(dāng)前狀態(tài)總結(jié)通用表達(dá)式樹(shù)實(shí)現(xiàn)已經(jīng)完成。四元數(shù)可在 Neon 寄存器中進(jìn)行存儲(chǔ)和運(yùn)算。通用算法無(wú)需修改即可獲得平臺(tái)優(yōu)化的性能??稍诓煌脚_(tái)使用不同 SIMD 優(yōu)化實(shí)現(xiàn)而不改變接口實(shí)現(xiàn)開(kāi)放–封閉原則OCP。1? 平臺(tái)特化ARM Neon32 四元數(shù)函數(shù)templateplt::simd::Neon32Family SIMDinlineautooperator-(Quatfloat,SIMDq)-Quatfloat,SIMD{float32x4_t valueq.NeonVal();float32x4_t negation(-q).NeonVal();float32x4_t resultvcopyq_laneq_f32(negation,0,value,0);returnQuatfloat,SIMD(result);}針對(duì) Neon32 平臺(tái)的四元數(shù)取負(fù)操作。使用 Neon SIMD 寄存器float32x4_t將四個(gè)浮點(diǎn)數(shù)打包到單個(gè)寄存器。延遲求值仍然生效表達(dá)式樹(shù)可以使用這個(gè)特化類型執(zhí)行運(yùn)算。vcopyq_laneq_f32是 Neon 特定的向量操作將特定元素復(fù)制或重新排列。1.1 平臺(tái)特化使用示例Quatfloateval(Quatfloata,Quatfloatb,Quatfloatc){return(a*bc)/(a-c);}對(duì)于 Neon32 特化a, b, c的數(shù)據(jù)會(huì)在 Neon 寄存器中進(jìn)行運(yùn)算。通用表達(dá)式樹(shù)和算法無(wú)需修改依然適用。2? SSE 平臺(tái)特化2.1 構(gòu)建系統(tǒng)更新創(chuàng)建新的工具鏈文件并設(shè)置set(PLT_SIMD SSE)SSE 平臺(tái)使用 128-bit 寄存器可同時(shí)存放 4 個(gè)浮點(diǎn)數(shù)float不支持 2 個(gè) double 同時(shí)存儲(chǔ)。2.2 SSE 特性頭文件namespaceplt::simd{structSse:Common{};templatetypenameSIMDconceptSseFamilystd::derived_fromSIMD,Sse;}用于標(biāo)識(shí) SSE 平臺(tái)方便模板約束。2.3 四元數(shù) SSE 特化類templateclassQuatfloat,plt::simd::Sse{__m128 value_;public:usingScalarfloat;Quat(Scalar w,Scalar x,Scalar y,Scalar z){value__mm_setr_ps(w,x,y,z);// 加載到 SSE 寄存器}Scalarw()constnoexcept{return_mm_cvtss_f32(SseVal());}Scalarx()constnoexcept{return_mm_cvtss_f32(_mm_shuffle_ps(SseVal(),SseVal(),_MM_SHUFFLE(1,1,1,1)));}Scalary()constnoexcept{return_mm_cvtss_f32(_mm_shuffle_ps(SseVal(),SseVal(),_MM_SHUFFLE(2,2,2,2)));}Scalarz()constnoexcept{return_mm_cvtss_f32(_mm_shuffle_ps(SseVal(),SseVal(),_MM_SHUFFLE(3,3,3,3)));}__m128SseVal()constnoexcept{returnvalue_;}};__m128表示 SSE 寄存器存儲(chǔ)四個(gè) float。使用_mm_setr_ps加載四個(gè)浮點(diǎn)數(shù)。通過(guò)_mm_shuffle_ps提取寄存器中對(duì)應(yīng)的分量。訪問(wèn)器保證對(duì) SSE 寄存器的安全讀取。2.4 SSE 平臺(tái)的標(biāo)量運(yùn)算點(diǎn)積templateplt::simd::Sse SIMDinlineautoDot(Quatfloat,SIMDlhs,Quatfloat,SIMDrhs)-float{__m128 squares_mm_mul_ps(lhs.SseVal(),rhs.SseVal());// 分量乘法__m128 badc_mm_shuffle_ps(squares,squares,_MM_SHUFFLE(2,3,0,1));// 調(diào)整順序__m128 pairs_mm_add_ps(squares,badc);// 前兩兩相加__m128 bbaa_mm_shuffle_ps(pairs,pairs,_MM_SHUFFLE(0,1,2,3));__m128 dp_mm_add_ps(pairs,bbaa);// 匯總到單一向量floatresult_mm_cvtss_f32(dp);// 提取結(jié)果returnresult;}SSE 內(nèi)置函數(shù)實(shí)現(xiàn) 4 分量的快速點(diǎn)積。所有運(yùn)算在寄存器中完成避免數(shù)據(jù)搬運(yùn)到通用寄存器。3? 多平臺(tái)支持與獨(dú)立優(yōu)化現(xiàn)在支持兩種平臺(tái)Neon32 和 SSE。優(yōu)化是完全獨(dú)立的Neon32 使用 ARM SIMD 寄存器。SSE 使用 x86 SSE 寄存器。沒(méi)有使用任何#if或#ifdef條件編譯。每個(gè)平臺(tái)只包含該平臺(tái)特定的頭文件和內(nèi)建函數(shù)。通用表達(dá)式樹(shù)算法無(wú)需修改即可使用平臺(tái)優(yōu)化實(shí)現(xiàn)。4? 處理特性修訂Feature RevisionsSSE2 支持 128-bit 寄存器同時(shí)可存儲(chǔ) 2 個(gè) double。對(duì) SSE2 平臺(tái)可新增以下類型Quatfloat, Sse2Quatdouble, Sse2特化步驟與 SSE 相似模板類和函數(shù)可復(fù)用只需修改類型和寄存器指令。5? 總結(jié)四元數(shù)類實(shí)現(xiàn)遵循 OCP 原則添加新平臺(tái)Neon32、SSE、SSE2無(wú)需修改已有平臺(tái)代碼?,F(xiàn)有算法和表達(dá)式樹(shù)通用實(shí)現(xiàn)不受影響。平臺(tái)特化與通用實(shí)現(xiàn)解耦通用實(shí)現(xiàn)負(fù)責(zé)算法邏輯。平臺(tái)特化負(fù)責(zé)寄存器布局和 SIMD 優(yōu)化。跨平臺(tái)架構(gòu)的關(guān)鍵點(diǎn)模板 概念Concepts定義接口。特化類實(shí)現(xiàn)平臺(tái)特定優(yōu)化。延遲求值Expression Tree保證組合性和性能。1? SSE2 特性與類實(shí)現(xiàn)1.1 SSE2 平臺(tái)頭文件#defineSIMD_HAS_SSE2#includeSse.hnamespaceplt::simd{structSse2:Sse{};templatetypenameSIMDconceptSse2FamilySseFamilySIMDstd::derived_fromSIMD,Sse2;}SSE2 繼承自 SSEstruct Sse2 : Sse {}。Sse2Family概念約束模板參數(shù)確保其為 SSE 家族成員且派生自 Sse2。模板約束保證了重載解析優(yōu)先選擇更特化的平臺(tái)實(shí)現(xiàn)。1.2 Quatfloat, Sse2 特化templateclassQuatfloat,plt::simd::Sse2:publicQuatfloat,plt::simd::Sse{usingQuatfloat,plt::simd::Sse::Quat;};直接繼承 SSE 特化實(shí)現(xiàn)復(fù)用。構(gòu)造函數(shù)、訪問(wèn)器等直接從 SSE 特化繼承。1.3 Quatdouble, Sse2 特化templateclassQuatdouble,plt::simd::Sse2{__m128d wx_;// w, x__m128d yz_;// y, zpublic:usingScalardouble;Quat()default;Quat(Scalar w,Scalar x,Scalar y,Scalar z){wx__mm_set_pd(x,w);yz__mm_set_pd(z,y);}templateQuaternion QQuat(constQrhs):Quat(static_castScalar(rhs.w()),static_castScalar(rhs.x()),static_castScalar(rhs.y()),static_castScalar(rhs.z())){}Quat(__m128d wx,__m128d yz):wx_(wx),yz_(yz){}Scalarw()const{return_mm_cvtsd_f64(SseWx());}Scalarx()const{return_mm_cvtsd_f64(_mm_unpackhi_pd(SseWx(),SseWx()));}Scalary()const{return_mm_cvtsd_f64(SseYz());}Scalarz()const{return_mm_cvtsd_f64(_mm_unpackhi_pd(SseYz(),SseYz()));}__m128dSseWx()const{returnwx_;}__m128dSseYz()const{returnyz_;}};利用 SSE2 128-bit 寄存器存儲(chǔ) double 類型的 w,x 和 y,z。_mm_set_pd設(shè)置寄存器值。_mm_unpackhi_pd提取寄存器高位 double 值。1.4 SSE2 平臺(tái)點(diǎn)積函數(shù)templateplt::simd::Sse2 SIMDinlineautoDot(Quatdouble,SIMDlhs,Quatdouble,SIMDrhs)-double{__m128d w2x2_mm_mul_pd(lhs.SseWx(),rhs.SseWx());__m128d x2w2_mm_shuffle_pd(w2x2,w2x2,_MM_SHUFFLE2(0,1));__m128d wx2wx2_mm_add_pd(w2x2,x2w2);__m128d y2z2_mm_mul_pd(lhs.SseYz(),rhs.SseYz());__m128d z2y2_mm_shuffle_pd(y2z2,y2z2,_MM_SHUFFLE2(0,1));__m128d yz2yz2_mm_add_pd(y2z2,z2y2);__m128d dp_mm_add_pd(wx2wx2,yz2yz2);doubleresult_mm_cvtsd_f64(dp);returnresult;}SSE2 支持 double 的并行運(yùn)算。點(diǎn)積通過(guò)寄存器操作_mm_mul_pd,_mm_shuffle_pd,_mm_add_pd高效計(jì)算。2? SSE3 平臺(tái)擴(kuò)展SSE3 繼承 SSE2不需要新寄存器。float 和 double 特化類可復(fù)用 SSE2 特化。利用_mm_hadd_ps和_mm_hadd_pd實(shí)現(xiàn)更高效水平加法。2.1 float 點(diǎn)積 SSE3templateplt::simd::Sse3 SIMDinlineautoDot(Quatfloat,SIMDlhs,Quatfloat,SIMDrhs)-float{__m128 squares_mm_mul_ps(lhs.SseVal(),rhs.SseVal());// 分量乘法__m128 add1st_mm_hadd_ps(squares,squares);// 兩兩相加__m128 add2nd_mm_hadd_ps(add1st,add1st);// 全部求和floatresult_mm_cvtss_f32(add2nd);returnresult;}2.2 double 點(diǎn)積 SSE3templateplt::simd::Sse3 SIMDinlineautoDot(Quatdouble,SIMDlhs,Quatdouble,SIMDrhs)-double{__m128d w2x2_mm_mul_pd(lhs.SseWx(),rhs.SseWx());__m128d y2z2_mm_mul_pd(lhs.SseYz(),rhs.SseYz());__m128d add1_mm_hadd_pd(w2x2,y2z2);__m128d add2_mm_hadd_pd(add1,add1);doubleresult_mm_cvtsd_f64(add2);returnresult;}_mm_hadd_ps和_mm_hadd_pd是 SSE3 新增指令實(shí)現(xiàn)水平加法優(yōu)化。3? 函數(shù)重載解析與概念Concepts3.1 重載解析Overload Resolution編譯器根據(jù)函數(shù)候選列表選擇最佳匹配。若無(wú)最佳匹配報(bào)錯(cuò)為“ambiguous overload”。3.2 概念在重載解析中的作用概念不僅約束模板參數(shù)有效性類似enable_if還參與最佳匹配的選擇。對(duì)于類模板派生類的模板優(yōu)先于基類模板。概念組合概念可以在定義中組合其他概念。概念本身不能繼承但可通過(guò)“subsumption”確定優(yōu)先級(jí)。Subsumption一個(gè)概念比另一個(gè)概念更“特化”在重載解析中優(yōu)先選擇。4? 總結(jié)SSE2 與 SSE3 特化繼承關(guān)系SSE2 繼承 SSESSE3 繼承 SSE2。更特化的平臺(tái)優(yōu)先匹配保證性能優(yōu)化生效。浮點(diǎn)類型與寄存器布局float:__m128double:__m128d分成 wx_ 和 yz_ 兩個(gè)寄存器存儲(chǔ)。通用算法與平臺(tái)特化解耦表達(dá)式樹(shù)和通用算法無(wú)需修改即可支持新平臺(tái)。平臺(tái)優(yōu)化通過(guò)模板特化實(shí)現(xiàn)。C20 Concepts 與重載解析概念用于模板約束。更特化的概念或派生類優(yōu)先匹配保證正確調(diào)用平臺(tái)特化實(shí)現(xiàn)。1? Subsumption概念覆蓋在代碼中的作用1.1 概念定義與覆蓋關(guān)系structSse:Common{};structSse2:Sse{};templatetypenameSIMDconceptSseFamilystd::derived_fromSIMD,Sse;templatetypenameSIMDconceptSse2FamilySseFamilySIMDstd::derived_fromSIMD,Sse2;templatetypenameSIMDconceptSse2Derivedstd::derived_fromSIMD,Sse2;Sse2Family是 SseFamily 的子集當(dāng)Sse2FamilyDerived為 true 時(shí)SseFamilyDerived也為 true。但 Sse2Derived 并不覆蓋 SseFamily因此不能參與重載優(yōu)先匹配。概念覆蓋subsumption的作用概念 A 覆蓋概念 B → 對(duì) A 的約束更特化優(yōu)先匹配。這是 C20 模板重載選擇的關(guān)鍵機(jī)制。1.2 沒(méi)有概念覆蓋的函數(shù)重載問(wèn)題templatetypenameSIMDconceptSse3Familystd::derived_fromSIMD,Sse3;templateplt::simd::SseFamily SIMDinlineautooperator*(Quatfloat,SIMDlhs,Quatfloat,SIMDrhs)-Quatfloat,SIMD;templateplt::simd::Sse3Family SIMDinlineautooperator*(Quatfloat,SIMDlhs,Quatfloat,SIMDrhs)-Quatfloat,SIMD;問(wèn)題Sse3Family 僅是一個(gè)單獨(dú)標(biāo)簽概念沒(méi)有與 Sse2Family 或 SseFamily 的覆蓋關(guān)系。結(jié)果operator*調(diào)用會(huì)產(chǎn)生ambiguous overload重載二義性錯(cuò)誤。原因Sse3Family 的參數(shù)類型嚴(yán)格是 Sse3SseFamily 可接受更多類型但兩者沒(méi)有覆蓋關(guān)系編譯器無(wú)法確定哪一個(gè)函數(shù)優(yōu)先。1.3 有概念覆蓋的正確實(shí)現(xiàn)templatetypenameSIMDconceptSse2FamilySseFamilySIMDstd::derived_fromSIMD,Sse2;templatetypenameSIMDconceptSse3FamilySse2FamilySIMDstd::derived_fromSIMD,Sse3;特點(diǎn)Sse2Family 覆蓋 SseFamilySse3Family 覆蓋 Sse2Family覆蓋關(guān)系是可傳遞的transitive效果編譯器會(huì)優(yōu)先選擇最特化的概念對(duì)應(yīng)的函數(shù)Sse3Family。避免了重載二義性。2? 平臺(tái)特化與繼承策略2.1 SSE / SSE2 / SSE3數(shù)據(jù)類和函數(shù)在 SSE 上實(shí)現(xiàn)。SSE2 繼承 SSE 優(yōu)化函數(shù)無(wú)需額外代碼。SSE3 僅實(shí)現(xiàn)少量更優(yōu)化函數(shù)其余繼承 SSE2。結(jié)果新版本函數(shù)不會(huì)影響舊平臺(tái)。保持 OCP開(kāi)放-關(guān)閉原則強(qiáng)約束無(wú)需修改舊代碼也不需要重新編譯舊平臺(tái)。2.2 AVX 平臺(tái)AVX 引入 256-bit 寄存器Quat 無(wú)法直接使用寬寄存器仍繼承前代實(shí)現(xiàn)。Quat 可以完整放入單寄存器需新數(shù)據(jù)類型。問(wèn)題Quatdouble, Avx 若與 SSE4 共用 math 頭文件會(huì)出現(xiàn)寄存器不兼容錯(cuò)誤。初始頭文件拆分Quat.h, Quat_Sse.h還不夠需要進(jìn)一步分離函數(shù)實(shí)現(xiàn)。2.3 分離頭文件策略類定義與函數(shù)實(shí)現(xiàn)分離Quat.h / Quat_Sse.h / Quat_Avx.h → 數(shù)據(jù)類QuatMath.h / QuatMath_Sse.h / QuatMath_Avx.h → 函數(shù)實(shí)現(xiàn)AVX 示例QuatFloatMath_Avx.h包含QuatFloatMath_Sse4.h繼承 float 操作QuatDoubleMath_Avx.h不包含舊頭文件避免 double 操作不兼容好處避免不同平臺(tái) math 實(shí)現(xiàn)沖突保持舊平臺(tái)編譯結(jié)果不變 → 近乎“強(qiáng) OCP”3? 總結(jié)要點(diǎn)概念覆蓋SubsumptionSse3Family → Sse2Family → SseFamily確保模板重載正確選擇最特化版本。平臺(tái)隔離每個(gè)平臺(tái)的數(shù)據(jù)類型與函數(shù)實(shí)現(xiàn)獨(dú)立。新平臺(tái)不會(huì)影響舊平臺(tái)構(gòu)建。函數(shù)復(fù)用SSE / SSE2 / SSE3 / AVX 復(fù)用已有優(yōu)化函數(shù)減少冗余。OCP 實(shí)現(xiàn)新特性添加不修改舊代碼。分離數(shù)據(jù)類和函數(shù)實(shí)現(xiàn)保證不同平臺(tái)獨(dú)立優(yōu)化。C20 Concepts 的優(yōu)勢(shì)提供了類型約束和重載優(yōu)先級(jí)控制。通過(guò) subsumption 和派生關(guān)系可實(shí)現(xiàn)跨平臺(tái) SIMD 重載無(wú)二義性。代碼太多看不懂https://github.com/noahstein/Ark