最近學(xué)習(xí)百度apollo源碼,發(fā)現(xiàn)很多看不懂的代碼,因才疏學(xué)淺,只能通過上網(wǎng)搜索,逐步理解,然后將理解完成的內(nèi)容再次進行記錄,其中參考了很多其他博主的博客。
我覺得對于程序員來說,看優(yōu)秀的代碼是進步最快的方式,看代碼不僅要看懂代碼,還要看明白設(shè)計者設(shè)計該部分代碼的框架。
廢話不多少,接下來看一下apollo中基于C++類型萃取實現(xiàn)的結(jié)構(gòu)體成員變量或函數(shù)的存在性判斷的宏定義:DEFINE_TYPE_TRAIT該宏定義位于:cyber/base/macros.h中。
#define DEFINE_TYPE_TRAIT(name, func) \
template \
struct name { \
// 僅當(dāng)T是一個類類型時,“Class::func”才是存在的,從而這個泛型函數(shù)的實例化才是可行的
// 否則,就將觸發(fā)SFINAE
template \
static constexpr bool Test(decltype(&Class::func)*) {\
return true; \
} \
// 僅當(dāng)觸發(fā)SFINAE時,編譯器才會“被迫”選擇這個版本
template \
static constexpr bool Test(...) { \
return false; \
} \
\
static constexpr bool value = Test(nullptr); \
}; \
\
template \
constexpr bool name::value;
解讀這個宏定義創(chuàng)建了一個struct name的結(jié)構(gòu)體constexpr bool name
第6-15行使用了SFINAE機制,定義了模版類型的Test函數(shù)。具體參看【C++深陷】之“decltype”和C++模板SFINAE特性與反射機制
從名字可以知道這段代碼的目的是定義一個名為name的類型萃取器,這個萃取器的name::value是bool類型,可以判定T中是否有func函數(shù)。使用如下:
DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong)
//定義HasByteSize的結(jié)構(gòu)體,func為ByteSizeLong
DEFINE_TYPE_TRAIT 會根據(jù)宏參數(shù) name 創(chuàng)建一個同名的類型萃取模板類,并檢查模板類型參數(shù) T 中是否包含與宏參數(shù) func 同名的方法,若包含,則模板類的 value 成員被置為 true,否則置為 false。應(yīng)該注意的是,func 在 T 中必須是公有的,否則無法被發(fā)現(xiàn)。
所以 DEFINE_TYPE_TRAIT(HasByteSize, ByteSizeLong) 的具體含義是:創(chuàng)建類型萃取模板類 HasByteSize,HasByteSize可檢查模板類型參數(shù) T 中是否包含 ByteSizeLong方法。
HasByteSize::value \\ true 表示有A.ByteSizeLong()
//在宏定義中為name::value,即HasByteSize.value, Test(nullptr)
//這里的模版T就是A,那么4-7行Test模版中Class就是這里的A。
HasByteSize::value \\ false 表示沒有B.ByteSizeLong()
其中A和B可以是結(jié)構(gòu)體或者類。
SFINAE機制C++模板提供了一個SFINAE(subsitate failure is not an error)的機制(模板匹配失敗不是錯誤),這是模板里面一個非常有意思的特性,利用這個機制可以檢查一個結(jié)構(gòu)體是否包含某個成員等操作。c++語言本身沒有提供反射機制(也有利用pb實現(xiàn)反射),利用SFINAE機制,可以實現(xiàn)類似于反射的功能。
舉例#include#include// A類型包含size函數(shù)
struct A {int size() { return 0;
}
};
struct B {int Size() {return 1;
}
};
// type trait
templatestruct HasSize {templatestatic constexpr bool Test(decltype(&Class::size)*) {return true;
}
templatestatic constexpr bool Test(...) {return false;
}
static constexpr bool value = Test(nullptr);
};
int main() {if (!HasSize::value) {std::cout<< "hello world"<
上面代碼中,HasSize中有靜態(tài)的常量value,它的初值是通過調(diào)用結(jié)構(gòu)體的靜態(tài)成員函數(shù)Test(nullptr)來初始化的。
而它有兩個Test函數(shù),且都是constexpr修飾的,這表明函數(shù)參數(shù)及返回值在編譯器就要確定下來。
正是如此,如果Class有size函數(shù),那么
static constexpr bool Test(decltype(&Class::size)*) {return true;
}
在編譯期就可以替換成功,即
static constexpr bool Test(Func *) {return true;
}
value = Test(nullptr)也就自然而然被初始化為true。否則,便會是false。
運行上述結(jié)果,因為B::size()不存在,可以看到最后輸出了結(jié)果。
【C++深陷】之“decltype”
C++模板SFINAE特性與反射機制
由一道C++面試題引發(fā)的思考
深入探索單例設(shè)計模式:以百度 Apollo 為例
C++ type_traits和SFINAE的一點理解
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁名稱:百度apollo源碼學(xué)習(xí)(一)DEFINE-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://jinyejixie.com/article14/dpoide.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站內(nèi)鏈、網(wǎng)站收錄、定制網(wǎng)站、電子商務(wù)、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容