C++11 模板元編程 - 類型萃取


類型萃?。╰rait)的概念我們前面有介紹過??梢詫rait看做是一種靜態(tài)反射技術(shù),通過trait我們可以自動提取出想要的代碼元信息,避免讓客戶代碼顯示去提供這些信息,從而使得客戶代碼更加的簡潔。

在dates中,客戶可使用FakeSystem定義一個fake系統(tǒng),與SUT交互。FakeSystem擁有sendrecv接口,分別向SUT發(fā)送消息,以及從SUT接收消息。send的入?yún)⑹且粋€原型為void(Msg&)的lambda函數(shù),用于描述如何構(gòu)造Msg消息。

visitor.send([this](AccessReq& req)
        {
            req.capability = CAPABILITY;
        });

由于一個FakeSystem可以發(fā)送多種msg,所以send接口無法確定lambda的具體類型,因此send的參數(shù)只能定義為泛型參數(shù),它的原型為:

template<typename BUILDER>
void send(const BUILDER& builder);

這樣send就可以傳入各種構(gòu)造不同消息類型的lambda了,而且還可以調(diào)用原型一致的普通函數(shù)或者仿函數(shù),客戶使用起來非常簡潔。

現(xiàn)在我們來實現(xiàn)send。send中需要創(chuàng)建一個消息,然后交給builder去構(gòu)造。如下偽代碼:

template<typename BUILDER>
void send(const BUILDER& builder)
{
    Msg msg; // 這里Msg到底應(yīng)該是什么類型?
    builder(msg);
    // ...
}

上面代碼的問題在于,我們不知道Msg的類型!Msg的類型是由客戶傳入的不同builder決定的,例如visitor.send([this](AccessReq& req){...})中,Msg是AccessReq。換句話說,我們需要從傳入的lambda表達(dá)式的類型中獲取Msg的類型。

模板元編程可以幫助我們解決這個問題。還記得我們前面介紹的TLP庫中trait工具中的__lambda_para()嗎?于是代碼修改如下:

template<typename BUILDER> 
void send(const BUILDER& builder)
{
    using Msg = __lambda_para(BUILDER, 0); // 獲取BUILDER的參數(shù)列表中的第一個參數(shù)類型
    Msg msg;
    builder(msg);
    // ...
}

如上我們通過類型萃取,從客戶傳入的函數(shù)類型中取出了參數(shù)的類型,使得框架的接口保持了簡潔和靈活性。


類型選擇

返回 C++11模板元編程 - 目錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容