0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

講解消息分發(fā)的一種編譯期實現(xiàn)法

CPP開發(fā)者 ? 來源:CppMore ? 2023-08-23 14:38 ? 次閱讀

今天講消息分發(fā)的一種編譯期實現(xiàn)法。

編程是一門非常依賴邏輯的學(xué)科,邏輯分為形式邏輯和非形式邏輯,編程就屬于形式邏輯。形式邏輯指的是用數(shù)學(xué)的方式去抽象地分析命題,它有一套嚴(yán)謹(jǐn)?shù)臉?biāo)準(zhǔn)和公理系統(tǒng),對錯分明;而日常生活中使用的是非形式邏輯,它不存在標(biāo)準(zhǔn)和公理,也沒有絕對的對與錯。

根據(jù)哲學(xué)家大衛(wèi)·休謨在《人性論》中對于觀念之間連接的分類,我們能夠把邏輯關(guān)系分成三大類:相似關(guān)系、因果關(guān)系、承接關(guān)系。相似關(guān)系表示兩個組件結(jié)構(gòu)相同,去掉其中一個組件,也只會使功能不夠全面,并不會影響程序;因果關(guān)系表示兩個組件之間依賴性極強,沒有第一個組件,就沒有第二個組件,第二個組件依賴于第一個組件;承接關(guān)系表示兩個組件都是局部,只有組合起來,才能構(gòu)成一個整體。

消息分發(fā)就屬于因果關(guān)系,我們需要依賴 A,去執(zhí)行 B,沒有 A 就沒有 B。同樣屬于因果關(guān)系的術(shù)語還有邏輯分派、模式匹配、定制點的表示方式等等,它們本質(zhì)都是在描述一類東西,只是有時候側(cè)重點不同。

條件關(guān)系也屬于因果關(guān)系的范疇,是編程中邏輯最重的關(guān)系。試想沒有if else,你還能寫出多少程序?世界是復(fù)雜的,問題也是復(fù)雜的,因果關(guān)系必不可少。

消息分發(fā),或稱邏輯分派,就是一種簡化條件關(guān)系表達(dá)方式的技術(shù)。它適用于存在大量因果的情境,此時若是使用原始的if else,則無法適應(yīng)動態(tài)發(fā)展的世界。

C++ 中,最典型、也非常有用的一種方式就是采用map,因作為 key,果作為 value,因是標(biāo)識符,果是回調(diào)函數(shù)。由于這種方式發(fā)生于運行期,所以也稱為動態(tài)消息分發(fā)。

本文要講的,是 C++20 才得以實現(xiàn)的另外一種方式,發(fā)生于編譯期的靜態(tài)消息分發(fā)技術(shù)。

稱為消息分發(fā),一般是在網(wǎng)絡(luò)通信的情境下。正常情境下,程序是順序執(zhí)行的,所以完全可以使用if else來實現(xiàn)因果邏輯,因為組件與組件之間距離較近,屬于同一模塊;而網(wǎng)絡(luò)情境下,一個組件可以瞬間跳躍到距離非常遠(yuǎn)的另一個組件,這兩個組件甚至不在同一臺設(shè)備上,一臺設(shè)備可能在上海,另一臺在北京,此時如何讓這兩個組件進(jìn)行溝通?也就是說,A 組件里面的某個函數(shù)執(zhí)行條件不滿足,如何簡單地跳到 B、C、D、E…… 這些組件的某個函數(shù)中去處理?這種遠(yuǎn)距離的程序因果邏輯,通過消息分發(fā)組件能夠非常絲滑地表示。

消息分發(fā)的標(biāo)識符一般采用字符串表示,到了 C++20 支持 string literal NTTP 才得以在編譯期實現(xiàn)一套可用的相關(guān)組件。

因此首先,我們得實現(xiàn)一個 string literal 以在編譯期使用。


		1template<std::size_tN> 2structstring_literal{ 3//strisareferencetoanarrayNofconstantchar 4constexprstring_literal(charconst(&str)[N]){ 5std::copy_n(str,N,value); 6} 7 8charvalue[N]; 9};
通過這種方式,我們定義了編譯期能夠使用的字符串組件,它能夠直接當(dāng)作模板參數(shù)使用。
然后,定義我們的分發(fā)器。

		1template  2structdispatcher{  3template  4constexprautoexecute_if(charconst*cause)const{  5if(C==cause)handler();  6}  7  8constexprautoexecute(charconst*cause)const{  9(execute_if(cause),...); 10} 11};
代碼非常精簡,分發(fā)器可以包含很多「因」,使用可變模板參數(shù) Cs 進(jìn)行表示。如果得到一個具體的「因」,我們需要找到對應(yīng)的「果」,因此免不了遍歷 Cs,借助 Fold expressions,一行代碼優(yōu)雅地搞定。通過 execute_if 來查找是否存在對應(yīng)的「因」,也就是對比字符串是否相等,查找到則調(diào)用相應(yīng)的「果」,也就是具體的處理函數(shù) handler()
接著,需要定義一個默認(rèn)的因果,即如果沒有定義相應(yīng)的處理函數(shù)時,所調(diào)用的一個默認(rèn)處理函數(shù)。

		1//defaultimplementation 2template 3inlineconstexprautohandler=[]{std::cout<"defaulteffect ";};
因為是模板參數(shù),所以它能夠處理所有的「因」。
通過特化,我們能夠在任何地方,定義任何因果。比如:

		1//opt-incustomizationpoints 2template<>inlineconstexprautohandler<"cause1">=[]{std::cout<"customizationpointseffect1 ";}; 3template<>inlineconstexprautohandler<"cause2">=[]{std::cout<"customizationpointseffect2 ";};
默認(rèn)版本和定制版本之間是相似關(guān)系,即便不提供定制版本,也會不影響程序的功能。
由于特化更加特殊,所以決議時會首先考慮這些因果對。但是,此時有巨大的重復(fù),我們通過宏來自動生成重復(fù)代碼:

		1#define_(name)template<>inlineconstexprautohandler<#name> 2 3//opt-incustomizationpoints 4_(cause1)=[]{std::cout<"customizationpointseffect1 ";}; 5_(cause2)=[]{std::cout<"customizationpointseffect2 ";};
現(xiàn)在定制起來就更加方便、簡潔。 最后,具體使用。

		1intmain(){ 2constexprstring_literalcause_1{"cause1"}; 3constexprdispatcher"cause2","cause3">dispatch; 4dispatch.execute(cause_1); 5dispatch.execute("cause2"); 6dispatch.execute("cause3"); 7}
相比動態(tài)消息分發(fā),這種方式有兩個巨大的優(yōu)勢,其一是編譯期,其二是定制時可以在任何地方。動態(tài)消息分發(fā)一般需要調(diào)用 dispatch.add_handler(cause, effect),因為是成員函數(shù),所以限制了定制地方,必須得在對象所在模塊,而靜態(tài)消息分發(fā)這種全局定義特化的方式,則沒有這種限制。
目前其實還存在兩個問題,第一是 C == cause 并沒有相應(yīng)的比較操作符,第二是 dispatch.execute(cause_1) 并不能直接傳遞,因為 char const*string_literal 畢竟不是同一種類型??梢酝ㄟ^添加運算符重載和隱式轉(zhuǎn)換來解決:

		1template<std::size_tN>  2structstring_literal{  3//...  4  5friendbooloperator==(string_literalconst&s,charconst*cause){  6returnstd::strncmp(s.value,cause,N)==0;  7}  8  9operatorcharconst*()const{ 10returnvalue; 11} 12 13//... 14};
			現(xiàn)在以上靜態(tài)消息分發(fā)組件就能夠正常使用了。完整的代碼如下:

		1template<std::size_tN>  2structstring_literal{  3constexprstring_literal(charconst(&str)[N]){  4std::copy_n(str,N,value);  5}  6  7friendbooloperator==(string_literalconst&s,charconst*cause){  8returnstd::strncmp(s.value,cause,N)==0;  9} 10 11operatorcharconst*()const{ 12returnvalue; 13} 14 15charvalue[N]; 16}; 17 18//defaultimplementation 19template 20inlineconstexprautohandler=[]{std::cout<"defaulteffect ";}; 21 22#define_(name)template<>inlineconstexprautohandler<#name> 23 24//opt-incustomizationpoints 25_(cause1)=[]{std::cout<"customizationpointseffect1 ";}; 26_(cause2)=[]{std::cout<"customizationpointseffect2 ";}; 27 28 29template 30structdispatcher{ 31template 32constexprautoexecute_if(charconst*cause)const{ 33if(C==cause)handler(); 34} 35 36constexprautoexecute(charconst*cause)const{ 37(execute_if(cause),...); 38} 39}; 40 41intmain(){ 42constexprstring_literalcause_1{"cause1"}; 43constexprdispatcher"cause2","cause3">dispatch; 44dispatch.execute(cause_1); 45dispatch.execute("cause2"); 46dispatch.execute("cause3"); 47}
短短數(shù)十行代碼,便實現(xiàn)了一個威力強大的靜態(tài)消息分發(fā)組件,This is modern C++。
審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3521

    瀏覽量

    93262
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    566

    瀏覽量

    20384
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2085

    瀏覽量

    73300
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4670

    瀏覽量

    67760
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    646

    瀏覽量

    32664

原文標(biāo)題:編譯期消息分發(fā)?C++20 已能優(yōu)雅實現(xiàn)!

文章出處:【微信號:CPP開發(fā)者,微信公眾號:CPP開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    一種高性能多通道通用DMA設(shè)計與實現(xiàn)

    為充分發(fā)揮異構(gòu)多核DSP芯片的實時計算能力,設(shè)計并實現(xiàn)一種高性能多通道的通用DMA,該DMA最大支持64個通道的數(shù)據(jù)搬運,并支持維、二維、轉(zhuǎn)置以及級聯(lián)描述符等多種傳輸模式。芯片實測
    的頭像 發(fā)表于 11-20 15:52 ?1064次閱讀
    <b class='flag-5'>一種</b>高性能多通道通用DMA設(shè)計與<b class='flag-5'>實現(xiàn)</b>

    介紹一種使用WSL來編譯nodemcu固件的方法

    本文將介紹一種使用WSL來編譯nodemcu固件的方法。
    發(fā)表于 02-15 07:34

    如何去實現(xiàn)一種RK3308系統(tǒng)交叉編譯的設(shè)計

    如何去實現(xiàn)一種RK3308系統(tǒng)交叉編譯的設(shè)計?有哪些編譯步驟?
    發(fā)表于 03-09 07:57

    一種用于反編譯代碼與源代碼的比較算法

    現(xiàn)有反編譯器產(chǎn)生的代碼與對應(yīng)的源代碼之間存在差異,找到并理解差異有助于改進(jìn)并完善反編譯器的設(shè)計。該文給出一種適用于C 語言反編譯代碼與源代碼的比較算法。該算法以語
    發(fā)表于 03-21 15:08 ?10次下載

    一種健壯的計算安全的分布式密鑰分發(fā)方案

    對基于Decisional Diffie-Hellmen 假設(shè)計算安全的分布式密鑰分發(fā)方案進(jìn)行改進(jìn),在其基礎(chǔ)上利用可驗證秘密共享和知識證明,提出一種健壯的計算安全的分布式密鑰分發(fā)方案,以抵抗主動
    發(fā)表于 06-17 09:39 ?22次下載

    一種分布式編譯系統(tǒng)的設(shè)計與實現(xiàn)

    本文針對當(dāng)前大型軟件生成時間過長的問題,在MSBuild 生成引擎的基礎(chǔ)上,提出并實現(xiàn)一種利用集群進(jìn)行分布式編譯的系統(tǒng),以降低在MSBuild 平臺上的產(chǎn)品每次編譯所需要的時間
    發(fā)表于 01-15 14:16 ?18次下載

    一種6_25Gb_s帶預(yù)加重結(jié)構(gòu)的低壓差分發(fā)送器_陳浩

    一種6_25Gb_s帶預(yù)加重結(jié)構(gòu)的低壓差分發(fā)送器_陳浩
    發(fā)表于 01-07 22:14 ?1次下載

    一種EPCCL理論編譯算法

    to knowledge compilation based on hyper extension rule).該算法適合難解類SAT問題的知識編譯,也是一種可并行的知識編譯算法.研究了如何
    發(fā)表于 12-26 10:39 ?0次下載

    一種支持單雙模式選擇的SIMD編譯優(yōu)化算法

    和SIMD指令來實現(xiàn),然而現(xiàn)有的編譯框架無法對這些特殊的SIMD指令提供支持。由于BWDSPlOO擁有豐富的SIMD向量化資源,且其所運用的雷達(dá)數(shù)字信號處理領(lǐng)域?qū)Τ绦虻男阅芤髽O高,因此針對BWDSPlOO結(jié)構(gòu)的特點,在傳統(tǒng)Open64
    發(fā)表于 01-05 10:28 ?0次下載
    <b class='flag-5'>一種</b>支持單雙模式選擇的SIMD<b class='flag-5'>編譯</b>優(yōu)化算法

    一種短波軟件無線電臺的實現(xiàn)講解

    一種短波軟件無線電臺的實現(xiàn)講解說明。
    發(fā)表于 03-25 09:30 ?11次下載
    <b class='flag-5'>一種</b>短波軟件無線電臺的<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>講解</b>

    一種基于公交系統(tǒng)的任務(wù)差異化分發(fā)方法

    、參與數(shù)量、感知區(qū)域類型等帶來的挑戰(zhàn)。基于此,該文利用城市中公交載體的軌跡可預(yù)測、活動覆蓋范圍大、乘客節(jié)點自主聚集且交互時間有保證等優(yōu)勢,提出了一種基于公交系統(tǒng)的任務(wù)差異化分發(fā)方法。首先,利用泰森多邊形的劃
    發(fā)表于 03-31 09:11 ?4次下載
    <b class='flag-5'>一種</b>基于公交系統(tǒng)的任務(wù)差異化<b class='flag-5'>分發(fā)</b>方法

    FPGA_ASIC-一種改進(jìn)的2D-DCT的FPGA實現(xiàn)

    FPGA_ASIC-一種改進(jìn)的2D-DCT的FPGA實現(xiàn)(核達(dá)中遠(yuǎn)通電源技術(shù)有限公司招聘文員嗎?)-該文檔為FPGA_ASIC-一種改進(jìn)的2D-DCT的FPGA實現(xiàn)
    發(fā)表于 09-16 10:35 ?4次下載
    FPGA_ASIC-<b class='flag-5'>一種</b>改進(jìn)的2D-DCT的FPGA<b class='flag-5'>實現(xiàn)</b>

    電子學(xué)報第七一種可配置的CNN協(xié)加速器的FPGA實現(xiàn)方法》

    電子學(xué)報第七一種可配置的CNN協(xié)加速器的FPGA實現(xiàn)方法》
    發(fā)表于 11-18 16:31 ?15次下載

    如何通過poly實現(xiàn)C++編譯多態(tài)

      而folly::poly出來的晚些,主要使用c++的新特性來實現(xiàn)相關(guān)的功能,依賴比較少,所以本文將更多的以poly的實現(xiàn)來分析編譯
    的頭像 發(fā)表于 12-05 09:10 ?561次閱讀

    分享一種路由重分發(fā)的標(biāo)準(zhǔn)解決方案

    路由重分發(fā)技術(shù)在現(xiàn)網(wǎng)環(huán)境中是一種很常見的技術(shù),所以其地位也非常重要。很多教程在在講路由重分發(fā)的時候,只講了重分發(fā)的操作卻沒有說現(xiàn)網(wǎng)環(huán)境中
    的頭像 發(fā)表于 05-05 08:59 ?887次閱讀
    分享<b class='flag-5'>一種</b>路由重<b class='flag-5'>分發(fā)</b>的標(biāo)準(zhǔn)解決方案